diff mbox series

[1/2] hw/mips/boston: Support initrd for ELF kernel

Message ID 20220813162720.60008-2-jiaxun.yang@flygoat.com
State New
Headers show
Series hw/mips/boston: Initrd support | expand

Commit Message

Jiaxun Yang Aug. 13, 2022, 4:27 p.m. UTC
When loading ELF kernel we can just load out initrd after DTB
and append initrd information to DeviceTree's chosen node.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 hw/mips/boston.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
diff mbox series

Patch

diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index d2ab9da1a0..5145179951 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -73,6 +73,8 @@  struct BostonState {
 
     hwaddr kernel_entry;
     hwaddr fdt_base;
+    hwaddr initrd_base;
+    hwaddr initrd_end;
 };
 
 enum {
@@ -383,6 +385,14 @@  static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
         return NULL;
     }
 
+    if (s->initrd_base) {
+        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                             s->initrd_base);
+
+        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                             s->initrd_end);
+    }
+
     ram_low_sz = MIN(256 * MiB, machine->ram_size);
     ram_high_sz = machine->ram_size - ram_low_sz;
     qemu_fdt_setprop_sized_cells(fdt, "/memory@0", "reg",
@@ -804,6 +814,35 @@  static void boston_mach_init(MachineState *machine)
                 dtb_file_data = create_fdt(s, boston_memmap, &dt_size);
             }
 
+            if (machine->initrd_filename) {
+                /* We want to leave low 128 MiB memory for kernelrelocation */
+                hwaddr initrd_paddr = MAX(128 * MiB,
+                                         QEMU_ALIGN_UP(dtb_paddr + dt_size,
+                                         64 * KiB));
+                int maxsz = boston_memmap[BOSTON_LOWDDR].size - initrd_paddr;
+
+                if (maxsz <= 0) {
+                        error_report("no space left for ramdisk '%s'",
+                                     machine->initrd_filename);
+                        exit(1);
+                }
+
+                int size = load_ramdisk(machine->initrd_filename,
+                                        initrd_paddr, maxsz);
+                if (size < 0) {
+                    size = load_image_targphys(machine->initrd_filename,
+                                               initrd_paddr, maxsz);
+                    if (size < 0) {
+                        error_report("could not load ramdisk '%s'",
+                                     machine->initrd_filename);
+                        exit(1);
+                    }
+                }
+
+                s->initrd_base = initrd_paddr;
+                s->initrd_end = s->initrd_base + size;
+            }
+
             dtb_load_data = boston_fdt_filter(s, dtb_file_data,
                                               NULL, &dtb_vaddr);