Skip to content

Commit 52895a0

Browse files
committed
hw: arm: boot: macho: support loading ramdisks
Ramdisks are loaded with -initrd. If you want to boot from a ramdisk, you also need to add "rd=md0" to the boot args.
1 parent fa1625e commit 52895a0

1 file changed

Lines changed: 45 additions & 0 deletions

File tree

hw/arm/boot.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,30 @@ static void macho_highest_lowest(struct mach_header_64* mh, uint64_t *lowaddr, u
998998
*lowaddr = low_addr_temp;
999999
*highaddr = high_addr_temp;
10001000
}
1001+
#define xnu_kPropNameLength 32
1002+
struct xnu_DeviceTreeNodeProperty {
1003+
char name[xnu_kPropNameLength];
1004+
uint32_t length;
1005+
char value[];
1006+
};
1007+
1008+
static void macho_add_ramdisk_to_dtb(uint8_t* dtb_data, size_t dtb_size, uint64_t ramdisk_addr, uint64_t ramdisk_size) {
1009+
struct xnu_DeviceTreeNodeProperty* dtNode = NULL;
1010+
for (size_t i = 0; i < dtb_size; i++) {
1011+
if (strncmp((const char*)dtb_data + i, "MemoryMapReserved-0", xnu_kPropNameLength) == 0) {
1012+
dtNode = (struct xnu_DeviceTreeNodeProperty*)(dtb_data + i);
1013+
break;
1014+
}
1015+
}
1016+
if (!dtNode) {
1017+
fprintf(stderr, "Can't write device tree node for ramdisk!\n");
1018+
abort();
1019+
}
1020+
strncpy(dtNode->name, "RAMDisk", xnu_kPropNameLength);
1021+
uint64_t* valuePtr = (uint64_t*)&dtNode->value;
1022+
valuePtr[0] = ramdisk_addr;
1023+
valuePtr[1] = ramdisk_size;
1024+
}
10011025

10021026
#define VAtoPA(addr) (((addr) & 0x3fffffff) + mem_base + kernel_load_offset)
10031027

@@ -1043,13 +1067,34 @@ static uint64_t arm_load_macho(struct arm_boot_info *info, uint64_t *pentry, Add
10431067
ret = true;
10441068

10451069
uint64_t load_extra_offset = high_addr_temp;
1070+
1071+
uint64_t ramdisk_address = load_extra_offset;
1072+
gsize ramdisk_size = 0;
1073+
1074+
// load ramdisk if exists
1075+
if (info->initrd_filename) {
1076+
uint8_t* ramdisk_data = NULL;
1077+
if (g_file_get_contents(info->initrd_filename, (char**) &ramdisk_data, &ramdisk_size, NULL)) {
1078+
info->initrd_filename = NULL;
1079+
rom_add_blob_fixed_as("xnu_ramdisk", ramdisk_data, ramdisk_size, VAtoPA(ramdisk_address), as);
1080+
load_extra_offset = (load_extra_offset + ramdisk_size + 0xffffull) & ~0xffffull;
1081+
g_free(ramdisk_data);
1082+
} else {
1083+
fprintf(stderr, "ramdisk failed?!\n");
1084+
abort();
1085+
}
1086+
}
1087+
10461088
uint64_t dtb_address = load_extra_offset;
10471089
gsize dtb_size = 0;
10481090
// load device tree
10491091
if (info->dtb_filename) {
10501092
uint8_t* dtb_data = NULL;
10511093
if (g_file_get_contents(info->dtb_filename, (char**) &dtb_data, &dtb_size, NULL)) {
10521094
info->dtb_filename = NULL;
1095+
if (ramdisk_size != 0) {
1096+
macho_add_ramdisk_to_dtb(dtb_data, dtb_size, VAtoPA(ramdisk_address), ramdisk_size);
1097+
}
10531098
rom_add_blob_fixed_as("xnu_dtb", dtb_data, dtb_size, VAtoPA(dtb_address), as);
10541099
load_extra_offset = (load_extra_offset + dtb_size + 0xffffull) & ~0xffffull;
10551100
g_free(dtb_data);

0 commit comments

Comments
 (0)