Commit a80274c31bd94f7a345934d2544075a6d183ebac
1 parent
0aeaa8ce
Large kernel initrd fix (initial patch by Daniel Jacobowitz).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2562 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
26 additions
and
3 deletions
hw/pc.c
... | ... | @@ -32,9 +32,11 @@ |
32 | 32 | #define LINUX_BOOT_FILENAME "linux_boot.bin" |
33 | 33 | |
34 | 34 | #define KERNEL_LOAD_ADDR 0x00100000 |
35 | -#define INITRD_LOAD_ADDR 0x00600000 | |
35 | +#define MAX_INITRD_LOAD_ADDR 0x38000000 | |
36 | 36 | #define KERNEL_PARAMS_ADDR 0x00090000 |
37 | 37 | #define KERNEL_CMDLINE_ADDR 0x00099000 |
38 | +/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ | |
39 | +#define ACPI_DATA_SIZE 0x10000 | |
38 | 40 | |
39 | 41 | static fdctrl_t *floppy_controller; |
40 | 42 | static RTCState *rtc_state; |
... | ... | @@ -452,6 +454,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, |
452 | 454 | char buf[1024]; |
453 | 455 | int ret, linux_boot, initrd_size, i; |
454 | 456 | ram_addr_t ram_addr, vga_ram_addr, bios_offset, vga_bios_offset; |
457 | + ram_addr_t initrd_offset; | |
455 | 458 | int bios_size, isa_bios_size, vga_bios_size; |
456 | 459 | PCIBus *pci_bus; |
457 | 460 | int piix3_devfn = -1; |
... | ... | @@ -599,8 +602,28 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, |
599 | 602 | |
600 | 603 | /* load initrd */ |
601 | 604 | initrd_size = 0; |
605 | + initrd_offset = 0; | |
602 | 606 | if (initrd_filename) { |
603 | - initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); | |
607 | + initrd_size = get_image_size (initrd_filename); | |
608 | + if (initrd_size > 0) { | |
609 | + initrd_offset = (ram_size - initrd_size) & TARGET_PAGE_MASK; | |
610 | + /* Leave space for BIOS ACPI tables. */ | |
611 | + initrd_offset -= ACPI_DATA_SIZE; | |
612 | + /* Avoid the last 64k to avoid 2.2.x kernel bugs. */ | |
613 | + initrd_offset -= 0x10000; | |
614 | + if (initrd_offset > MAX_INITRD_LOAD_ADDR) | |
615 | + initrd_offset = MAX_INITRD_LOAD_ADDR; | |
616 | + | |
617 | + if (initrd_size > ram_size | |
618 | + || initrd_offset < KERNEL_LOAD_ADDR + ret) { | |
619 | + fprintf(stderr, | |
620 | + "qemu: memory too small for initial ram disk '%s'\n", | |
621 | + initrd_filename); | |
622 | + exit(1); | |
623 | + } | |
624 | + initrd_size = load_image(initrd_filename, | |
625 | + phys_ram_base + initrd_offset); | |
626 | + } | |
604 | 627 | if (initrd_size < 0) { |
605 | 628 | fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", |
606 | 629 | initrd_filename); |
... | ... | @@ -608,7 +631,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, |
608 | 631 | } |
609 | 632 | } |
610 | 633 | if (initrd_size > 0) { |
611 | - stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR); | |
634 | + stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, initrd_offset); | |
612 | 635 | stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size); |
613 | 636 | } |
614 | 637 | pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096, | ... | ... |