void initKernBootStruct( void ) { Node *node; int nameLen; static int init_done = 0; if ( !init_done ) { bootArgs = (boot_args *)malloc(sizeof(boot_args)); bootArgsPreLion = (boot_args_pre_lion *)malloc(sizeof(boot_args_pre_lion)); bootInfo = (PrivateBootInfo_t *)malloc(sizeof(PrivateBootInfo_t)); if (bootArgs == 0 || bootInfo == 0) stop("Couldn't allocate boot info\n"); bzero(bootArgs, sizeof(boot_args)); bzero(bootArgsPreLion, sizeof(boot_args_pre_lion)); bzero(bootInfo, sizeof(PrivateBootInfo_t)); // Get system memory map. Also update the size of the // conventional/extended memory for backwards compatibility. bootInfo->memoryMapCount = getMemoryMap( bootInfo->memoryMap, kMemoryMapCountMax, (unsigned long *) &bootInfo->convmem, (unsigned long *) &bootInfo->extmem ); if ( bootInfo->memoryMapCount == 0 ) { // BIOS did not provide a memory map, systems with // discontiguous memory or unusual memory hole locations // may have problems. bootInfo->convmem = getConventionalMemorySize(); bootInfo->extmem = getExtendedMemorySize(); } bootInfo->configEnd = bootInfo->config; bootArgs->Video.v_display = VGA_TEXT_MODE; DT__Initialize(); node = DT__FindNode("/", true); if (node == 0) { stop("Couldn't create root node"); } getPlatformName(platformName); nameLen = strlen(platformName) + 1; DT__AddProperty(node, "compatible", nameLen, platformName); DT__AddProperty(node, "model", nameLen, platformName); gMemoryMapNode = DT__FindNode("/chosen/memory-map", true); bootArgs->Version = kBootArgsVersion; bootArgs->Revision = kBootArgsRevision; bootArgsPreLion->Version = kBootArgsPreLionVersion; bootArgsPreLion->Revision = kBootArgsPreLionRevision; init_done = 1; } }
// Notify OS X that a ramdisk has been setup. XNU will attach this to /dev/md0 void md0Ramdisk() { RAMDiskParam ramdiskPtr; char filename[512]; const char* override_filename = 0; int fh = -1; int len; if (getValueForKey(kMD0ImageKey, &override_filename, &len, &bootInfo->bootConfig)) { // Use user specified md0 file sprintf(filename, "%s", override_filename); fh = open(filename, 0); if (fh < 0) { sprintf(filename, "rd(0,0)/Extra/Postboot.img"); fh = open(filename, 0); if (fh < 0) { sprintf(filename, "bt(0,0)/Extra/Postboot.img"); // Check /Extra if not in rd(0,0) fh = open(filename, 0); } } } if (fh >= 0) { verbose("Enabling ramdisk %s\n", filename); ramdiskPtr.size = file_size(fh); ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size); if (ramdiskPtr.size && ramdiskPtr.base) { // Read new ramdisk image contents in kernel memory. if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size) { AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid); Node* node = DT__FindNode("/chosen/memory-map", false); if (node != NULL) { DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr); } else { verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename); } } else { verbose("Unable to read md0 image %s.\n", filename); } } else { verbose("md0 image %s is empty.\n", filename); } close(fh); } }
void setupEfiDeviceTree(void) { EFI_CHAR8* ret = 0; EFI_CHAR16* ret16 = 0; size_t len = 0; Node *node; node = DT__FindNode("/", false); if (node == 0) stop("Couldn't get root node"); // We could also just do DT__FindNode("/efi/platform", true) // But I think eventually we want to fill stuff in the efi node // too so we might as well create it so we have a pointer for it too. node = DT__AddChild(node, "efi"); if (archCpuType == CPU_TYPE_I386) { DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (char*)FIRMWARE_ABI_32_PROP_VALUE); } else { DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_64_PROP_VALUE), (char*)FIRMWARE_ABI_64_PROP_VALUE); } DT__AddProperty(node, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32*)&FIRMWARE_REVISION); DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR); // TODO: Fill in other efi properties if necessary // Set up the /efi/runtime-services table node similar to the way a child node of configuration-table // is set up. That is, name and table properties Node *runtimeServicesNode = DT__AddChild(node, "runtime-services"); if (archCpuType == CPU_TYPE_I386) { // The value of the table property is the 32-bit physical address for the RuntimeServices table. // Since the EFI system table already has a pointer to it, we simply use the address of that pointer // for the pointer to the property data. Warning.. DT finalization calls free on that but we're not // the only thing to use a non-malloc'd pointer for something in the DT DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST32->RuntimeServices); } else { DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST64->RuntimeServices); } // Set up the /efi/configuration-table node which will eventually have several child nodes for // all of the configuration tables needed by various kernel extensions. gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table"); // Now fill in the /efi/platform Node Node *efiPlatformNode = DT__AddChild(node, "platform"); // NOTE WELL: If you do add FSB Frequency detection, make sure to store // the value in the fsbFrequency global and not an malloc'd pointer // because the DT_AddProperty function does not copy its args. if (Platform.CPU.FSBFrequency != 0) DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform.CPU.FSBFrequency); // Export TSC and CPU frequencies for use by the kernel or KEXTs if (Platform.CPU.TSCFrequency != 0) DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform.CPU.TSCFrequency); if (Platform.CPU.CPUFrequency != 0) DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform.CPU.CPUFrequency); // Export system-id. Can be disabled with SystemId=No in com.apple.Boot.plist if ((ret=getSystemID())) DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret); // Export SystemSerialNumber if present if ((ret16=getSmbiosChar16("SMserial", &len))) DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16); // Export Model if present if ((ret16=getSmbiosChar16("SMproductname", &len))) DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16); // Fill /efi/device-properties node. setupDeviceProperties(node); }
void initEFITree(void) { _EFI_DEBUG_DUMP("Entering initEFITree(%x)\n", gPlatform.ACPI.Guid.Data1); static char ACPI[] = "ACPI"; // The required information should be added to private_data.h static EFI_CHAR16 const MODEL_NAME[] = STATIC_MODEL_NAME; static EFI_CHAR16 const SYSTEM_SERIAL_NUMBER[] = STATIC_SYSTEM_SERIAL_NUMBER; DT__Initialize(); // Add and initialize gPlatform.DT.RootNode /* * The root node is available until the call to DT__Finalize, or the first call * to DT__AddChild with NULL as first argument. Which we don't do and thus we * can use it in the meantime, instead of defining a local / global variable. */ DT__AddProperty(gPlatform.DT.RootNode, "model", 5, ACPI); DT__AddProperty(gPlatform.DT.RootNode, "compatible", 5, ACPI); Node * efiNode = DT__AddChild(gPlatform.DT.RootNode, "efi"); DT__AddProperty(efiNode, "firmware-abi", 6, (gPlatform.ArchCPUType == CPU_TYPE_X86_64) ? "EFI64" : "EFI32"); DT__AddProperty(efiNode, "firmware-revision", sizeof(FIRMWARE_REVISION), (EFI_UINT32*) &FIRMWARE_REVISION); DT__AddProperty(efiNode, "firmware-vendor", sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*) FIRMWARE_VENDOR); // Initialize a global var, used by function setupEFITables later on, to // add the address to the boot arguments (done to speed up the process). gPlatform.EFI.Nodes.RuntimeServices = DT__AddChild(efiNode, "runtime-services"); // Initialize a global var, used by function addConfigurationTable later on, // to add the SMBIOS and ACPI tables (done to speed up the process). gPlatform.EFI.Nodes.ConfigurationTable = DT__AddChild(efiNode, "configuration-table"); Node * platformNode = DT__AddChild(efiNode, "platform"); gPlatform.EFI.Nodes.Platform = platformNode; // Satisfying AppleACPIPlatform.kext static EFI_UINT8 const DEVICE_PATHS_SUPPORTED[] = { 0x01, 0x00, 0x00, 0x00 }; DT__AddProperty(platformNode, "DevicePathsSupported", sizeof(DEVICE_PATHS_SUPPORTED), (EFI_UINT8*) &DEVICE_PATHS_SUPPORTED); // The use of sizeof() here is mandatory (to prevent breakage). DT__AddProperty(platformNode, "Model", sizeof(MODEL_NAME), (EFI_CHAR16*) MODEL_NAME); DT__AddProperty(platformNode, "SystemSerialNumber", sizeof(SYSTEM_SERIAL_NUMBER), (EFI_CHAR16*) SYSTEM_SERIAL_NUMBER); if (gPlatform.CPU.FSBFrequency) { _EFI_DEBUG_DUMP("Adding FSBFrequency property (%dMHz)\n", (gPlatform.CPU.FSBFrequency / 1000)); DT__AddProperty(platformNode, "FSBFrequency", sizeof(uint64_t), &gPlatform.CPU.FSBFrequency); } Node * chosenNode = DT__AddChild(gPlatform.DT.RootNode, "chosen"); if (chosenNode == 0) { stop("Couldn't create /chosen node"); // Mimics boot.efi } gPlatform.EFI.Nodes.MemoryMap = DT__AddChild(chosenNode, "memory-map"); // Adding the root path for kextcache. DT__AddProperty(chosenNode, "boot-device-path", 38, "\\System\\Library\\CoreServices\\boot.efi"); /* static EFI_UINT8 const BOOT_DEVICE_PATH[] = { 0x02, 0x01, 0x0C, 0x00, 0xD0, 0x41, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x02, 0x1F, 0x03, 0x12, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x2A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0B, 0x63, 0x34, 0x00, 0x00, 0x00, 0x00, 0x65, 0x8C, 0x53, 0x3F, 0x1B, 0xCA, 0x83, 0x38, 0xA9, 0xD0, 0xF0, 0x46, 0x19, 0x14, 0x8E, 0x31, 0x02, 0x02, 0x7F, 0xFF, 0x04, 0x00 }; DT__AddProperty(chosenNode, "boot-device-path", sizeof(BOOT_DEVICE_PATH), &BOOT_DEVICE_PATH); */ // Adding the default kernel name (mach_kernel) for kextcache. DT__AddProperty(chosenNode, "boot-file", sizeof(bootInfo->bootFile), bootInfo->bootFile); #if APPLE_STYLE_EFI static EFI_UINT8 const BOOT_FILE_PATH[] = { 0x04, 0x04, 0x50, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x04, 0x00 }; DT__AddProperty(chosenNode, "boot-file-path", sizeof(BOOT_FILE_PATH), (EFI_UINT8*) &BOOT_FILE_PATH); static EFI_UINT8 const BOOT_ARGS[] = { 0x00 }; DT__AddProperty(chosenNode, "boot-args", sizeof(BOOT_ARGS), (EFI_UINT8*) &BOOT_ARGS); /* Adding kIOHibernateMachineSignatureKey (IOHibernatePrivate.h). * * This 'Hardware Signature' (offset 8 in the FACS table) is calculated by the BIOS on a best effort * basis to indicate the base hardware configuration of the system such that different base hardware * configurations can have different hardware signature values. OSPM uses this information in waking * from an S4 state, by comparing the current hardware signature to the signature values saved in the * non-volatile sleep image. If the values are not the same, OSPM assumes that the saved non-volatile * image is from a different hardware configuration and cannot be restored. */ static EFI_UINT8 const MACHINE_SIGNATURE[] = { 0x00, 0x00, 0x00, 0x00 }; DT__AddProperty(chosenNode, "machine-signature", sizeof(MACHINE_SIGNATURE), (EFI_UINT8*) &MACHINE_SIGNATURE); #if ((MAKE_TARGET_OS & LION) == LION) // Used by boot.efi - cosmetic only node/properties on hacks. Node * kernelCompatNode = DT__AddChild(efiNode, "kernel-compatibility"); static EFI_UINT8 const COMPAT_MODE[] = { 0x01, 0x00, 0x00, 0x00 }; DT__AddProperty(kernelCompatNode, "i386", sizeof(COMPAT_MODE), (EFI_UINT8*) &COMPAT_MODE); DT__AddProperty(kernelCompatNode, "x86_64", sizeof(COMPAT_MODE), (EFI_UINT8*) &COMPAT_MODE); #endif // Adding the options node breaks AppleEFINVRAM (missing hardware UUID). // Node *optionsNode = DT__AddChild(gPlatform.DT.RootNode, "options"); // DT__AddProperty(optionsNode, "EFICapsuleResult", 4, "STAR"); // 53 54 41 52 #endif // DT__AddProperty(chosenNode, "boot-kernelcache-adler32", sizeof(uint64_t), adler32); gPlatform.EFI.Nodes.Chosen = chosenNode; #if INJECT_EFI_DEVICE_PROPERTIES static EFI_UINT8 const EFI_DEVICE_PROPERTIES[] = { STATIC_EFI_DEVICE_PROPERTIES }; _EFI_DEBUG_DUMP("Injecting EFI device-properties\n"); DT__AddProperty(efiNode, "device-properties", sizeof(EFI_DEVICE_PROPERTIES), (EFI_CHAR8*) &EFI_DEVICE_PROPERTIES); #endif _EFI_DEBUG_DUMP("Exiting initEFITree()\n"); _EFI_DEBUG_SLEEP(5); }