Skip to content

Commit

Permalink
hw/i386/pc: format load_linux function
Browse files Browse the repository at this point in the history
Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
liguang authored and stefanhaRH committed Mar 28, 2013
1 parent 9941afd commit 0f9d76e
Showing 1 changed file with 56 additions and 53 deletions.
109 changes: 56 additions & 53 deletions hw/i386/pc.c
Expand Up @@ -646,8 +646,8 @@ static long get_file_size(FILE *f)

static void load_linux(void *fw_cfg,
const char *kernel_filename,
const char *initrd_filename,
const char *kernel_cmdline,
const char *initrd_filename,
const char *kernel_cmdline,
hwaddr max_ram_size)
{
uint16_t protocol;
Expand All @@ -664,60 +664,62 @@ static void load_linux(void *fw_cfg,
/* load the kernel header */
f = fopen(kernel_filename, "rb");
if (!f || !(kernel_size = get_file_size(f)) ||
fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
MIN(ARRAY_SIZE(header), kernel_size)) {
fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
kernel_filename, strerror(errno));
exit(1);
fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
MIN(ARRAY_SIZE(header), kernel_size)) {
fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
kernel_filename, strerror(errno));
exit(1);
}

/* kernel protocol version */
#if 0
fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
#endif
if (ldl_p(header+0x202) == 0x53726448)
protocol = lduw_p(header+0x206);
else {
/* This looks like a multiboot kernel. If it is, let's stop
treating it like a Linux kernel. */
if (ldl_p(header+0x202) == 0x53726448) {
protocol = lduw_p(header+0x206);
} else {
/* This looks like a multiboot kernel. If it is, let's stop
treating it like a Linux kernel. */
if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
kernel_cmdline, kernel_size, header))
kernel_cmdline, kernel_size, header)) {
return;
protocol = 0;
}
protocol = 0;
}

if (protocol < 0x200 || !(header[0x211] & 0x01)) {
/* Low kernel */
real_addr = 0x90000;
cmdline_addr = 0x9a000 - cmdline_size;
prot_addr = 0x10000;
/* Low kernel */
real_addr = 0x90000;
cmdline_addr = 0x9a000 - cmdline_size;
prot_addr = 0x10000;
} else if (protocol < 0x202) {
/* High but ancient kernel */
real_addr = 0x90000;
cmdline_addr = 0x9a000 - cmdline_size;
prot_addr = 0x100000;
/* High but ancient kernel */
real_addr = 0x90000;
cmdline_addr = 0x9a000 - cmdline_size;
prot_addr = 0x100000;
} else {
/* High and recent kernel */
real_addr = 0x10000;
cmdline_addr = 0x20000;
prot_addr = 0x100000;
/* High and recent kernel */
real_addr = 0x10000;
cmdline_addr = 0x20000;
prot_addr = 0x100000;
}

#if 0
fprintf(stderr,
"qemu: real_addr = 0x" TARGET_FMT_plx "\n"
"qemu: cmdline_addr = 0x" TARGET_FMT_plx "\n"
"qemu: prot_addr = 0x" TARGET_FMT_plx "\n",
real_addr,
cmdline_addr,
prot_addr);
"qemu: real_addr = 0x" TARGET_FMT_plx "\n"
"qemu: cmdline_addr = 0x" TARGET_FMT_plx "\n"
"qemu: prot_addr = 0x" TARGET_FMT_plx "\n",
real_addr,
cmdline_addr,
prot_addr);
#endif

/* highest address for loading the initrd */
if (protocol >= 0x203)
initrd_max = ldl_p(header+0x22c);
else
initrd_max = 0x37ffffff;
if (protocol >= 0x203) {
initrd_max = ldl_p(header+0x22c);
} else {
initrd_max = 0x37ffffff;
}

if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
Expand All @@ -727,10 +729,10 @@ static void load_linux(void *fw_cfg,
fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);

if (protocol >= 0x202) {
stl_p(header+0x228, cmdline_addr);
stl_p(header+0x228, cmdline_addr);
} else {
stw_p(header+0x20, 0xA33F);
stw_p(header+0x22, cmdline_addr-real_addr);
stw_p(header+0x20, 0xA33F);
stw_p(header+0x22, cmdline_addr-real_addr);
}

/* handle vga= parameter */
Expand All @@ -755,23 +757,23 @@ static void load_linux(void *fw_cfg,
/* High nybble = B reserved for QEMU; low nybble is revision number.
If this code is substantially changed, you may want to consider
incrementing the revision. */
if (protocol >= 0x200)
header[0x210] = 0xB0;

if (protocol >= 0x200) {
header[0x210] = 0xB0;
}
/* heap */
if (protocol >= 0x201) {
header[0x211] |= 0x80; /* CAN_USE_HEAP */
stw_p(header+0x224, cmdline_addr-real_addr-0x200);
header[0x211] |= 0x80; /* CAN_USE_HEAP */
stw_p(header+0x224, cmdline_addr-real_addr-0x200);
}

/* load initrd */
if (initrd_filename) {
if (protocol < 0x200) {
fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
exit(1);
}
if (protocol < 0x200) {
fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
exit(1);
}

initrd_size = get_image_size(initrd_filename);
initrd_size = get_image_size(initrd_filename);
if (initrd_size < 0) {
fprintf(stderr, "qemu: error reading initrd %s\n",
initrd_filename);
Expand All @@ -787,14 +789,15 @@ static void load_linux(void *fw_cfg,
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);

stl_p(header+0x218, initrd_addr);
stl_p(header+0x21c, initrd_size);
stl_p(header+0x218, initrd_addr);
stl_p(header+0x21c, initrd_size);
}

/* load kernel and setup */
setup_size = header[0x1f1];
if (setup_size == 0)
setup_size = 4;
if (setup_size == 0) {
setup_size = 4;
}
setup_size = (setup_size+1)*512;
kernel_size -= setup_size;

Expand Down

0 comments on commit 0f9d76e

Please sign in to comment.