void initPlatform(int biosDevice) { memset(&gPlatform, 0, sizeof(gPlatform)); // Copied from cpu/dynamic_data.h to make printf work this early on. #if DEBUG_CPU || DEBUG_PLATFORM extern void setVideoMode(int mode); setVideoMode(0); // Switch to VGA_TEXT_MODE #endif #if ENABLE_HPET enableHPET(); #endif gPlatform.RevoBootVersionInfo = strdup(REVOBOOT_VERSION_INFO); // Example: "RevoBoot v1.0.04" _PLATFORM_DEBUG_DUMP("Booting with: %s\n", gPlatform.RevoBootVersionInfo); #if AUTOMATIC_SSDT_PR_CREATION || DEBUG_TURBO_RATIOS uint8_t cpu = 0; uint8_t numberOfCores = STATIC_CPU_NumCores; // Zero out CPU core ratio limits. for (; cpu < numberOfCores; cpu++) { gPlatform.CPU.CoreTurboRatio[cpu] = 0; // Get updated later on in: i386/libsaio/Intel/cpu.c } #endif // Jeroen: Initialized in cpu.c and used in ssdt_pr_generator.h gPlatform.CPU.NumberOfTurboRatios = 0; initCPUStruct(); /* * DHP: Booting with arch=i386 <i>and</i> setting this to CPU_TYPE_I386 * and setting the EFI_64_BIT directive in private_data to 0 allowed me * to boot in EFI32 mode. Even with my 64 bit configuration. Pretty sweet. * * Note to self: Get rid of gArchCPUType (global alarm) fast. */ gPlatform.ArchCPUType = gArchCPUType = getArchCPUType(); gPlatform.AddressWidth = (gPlatform.ArchCPUType == CPU_TYPE_X86_64) ? 8 : 4; gPlatform.ACPI.Guid = (EFI_GUID) EFI_ACPI_20_TABLE_GUID; gPlatform.SMBIOS.Guid = (EFI_GUID) EFI_SMBIOS_TABLE_GUID; #if INCLUDE_MPS_TABLE gPlatform.MPS.Guid = (EFI_GUID) EFI_MPS_TABLE_GUID; #endif // INCLUDE_MP_TABLE // Used in boot.c to verify the checksum (adler32) of pre-linked kernels. gPlatform.ModelID = strdup(SMB_PRODUCT_NAME); #if LOAD_MODEL_SPECIFIC_STATIC_DATA // Used in RevoBoot/i386/libsaio/ACPI/patcher.h, RevoBoot/i386/libsaio/efi.c // and RevoBoot/i386/libsaio/SMBIOS/static_data.h gPlatform.CommaLessModelID = removeChar(strdup(gPlatform.ModelID), ','); #endif // Determine system type based on product name. Used in // acpi/patcher.h to update FADT->Preferred_PM_Profile gPlatform.Type = (strncmp(gPlatform.ModelID, "MacBook", 7) == 0) ? 2 : 1; // Are we supposted to have a Mobile CPU? if (gPlatform.Type == 2 && gPlatform.CPU.Mobile == false) { // Yes (based on the model identifier) but we either failed // to detect a Mobile CPU, or we are using static CPU data. gPlatform.CPU.Mobile = true; // Will be initialized in cpu/cpu_dynamic.h (used in smbios/dynamic_data.h) } #if (MAKE_TARGET_OS == LION) gPlatform.OSVersion = strdup("10.7"); #elif (MAKE_TARGET_OS == MOUNTAIN_LION) gPlatform.OSVersion = strdup("10.8"); #else // Snow Leopard gPlatform.OSVersion = strdup("10.6"); #endif // _PLATFORM_DEBUG_DUMP("REVOBOOT_OS_TARGET: %d\n", REVOBOOT_OS_TARGET); gPlatform.OSType = (int) MAKE_TARGET_OS; _PLATFORM_DEBUG_DUMP("gPlatform.OSType: %d\n", gPlatform.OSType); // Target OS setting from either make or config/settings.h // gPlatform.OSVersion[3] = 0x34 + gPlatform.OSType; _PLATFORM_DEBUG_DUMP("gPlatform.OSVersion: %s\n", gPlatform.OSVersion); gPlatform.BIOSDevice = (biosDevice & kBIOSDevMask); // Device number masked with 0xFF. gPlatform.BootVolume = NULL; // Will be initialized in disk.c gPlatform.BootPartitionChain = NULL; // Will be initialized in sys.c gPlatform.RootVolume = NULL; // Will be initialized in disk.c (used in sys.c) gPlatform.RAM.SlotCount = 0; // Will be initialized further down (used in smbios/dynamic_data.h) gPlatform.KernelCachePath = strdup(kKernelCachePath); // Used in boot.c and driver.c _PLATFORM_DEBUG_DUMP("Kernel cache path: %s\n", gPlatform.KernelCachePath); #if USE_STATIC_SMBIOS_DATA // We don't have to do anything when static SMBIOS data is used. #elif OVERRIDE_DYNAMIC_MEMORY_DETECTION // Setup static STATIC_RAM_XXXX module info defined in config/settings.h const char * ramVendor[] = STATIC_RAM_VENDORS; const char * ramPartNumber[] = STATIC_RAM_PART_NUMBERS; const char * ramSerialNumber[] = STATIC_RAM_SERIAL_NUMBERS; #if DYNAMIC_RAM_OVERRIDE_SIZE int ramSize[] = DYNAMIC_RAM_OVERRIDE_SIZES; #endif int i = 0; // Loop through the static RAM vendors (might be different). for (; i < STATIC_RAM_SLOTS; i++) { gPlatform.RAM.SlotCount++; // We check for "N/A" so make sure you use that in config/settings.h if (strcmp(ramVendor[i], "N/A") != 0) { _PLATFORM_DEBUG_DUMP("Slot:%d, ", i); gPlatform.RAM.MODULE[i].InUse = true; gPlatform.RAM.MODULE[i].Type = DYNAMIC_RAM_OVERRIDE_TYPE; #if DYNAMIC_RAM_OVERRIDE_SIZE gPlatform.RAM.MODULE[i].Size = ramSize[i]; _PLATFORM_DEBUG_DUMP("Size:%d, ", gPlatform.RAM.MODULE[i].Size); #endif gPlatform.RAM.MODULE[i].Vendor = ramVendor[i]; gPlatform.RAM.MODULE[i].PartNumber = ramPartNumber[i]; gPlatform.RAM.MODULE[i].SerialNumber = ramSerialNumber[i]; _PLATFORM_DEBUG_DUMP("%s, %s, %s\n", gPlatform.RAM.MODULE[i].Vendor, gPlatform.RAM.MODULE[i].PartNumber, gPlatform.RAM.MODULE[i].SerialNumber); } else { // Properly initialized for: smbios/dynamic_data.h which relies on it. gPlatform.RAM.MODULE[i].InUse = false; } } _PLATFORM_DEBUG_DUMP("Static data for %d RAM BANKS used.\n", gPlatform.RAM.SlotCount); #endif _PLATFORM_DEBUG_SLEEP(15); initKernelBootConfig(); #if (LOAD_MODEL_SPECIFIC_EFI_DATA) /* * We need to call this much earlier in the boot process when static EFI data * is read from: /Extra/EFI[MacModelNN.bin]. Otherwise LoadFile (load.c) fails. */ initPartitionChain(); #endif initEFITree(); }
void boot(int biosdev) { zeroBSS(); mallocInit(0, 0, 0, mallocError); #if MUST_ENABLE_A20 // Enable A20 gate before accessing memory above 1 MB. if (fastEnableA20() != 0) { enableA20(); // Fast enable failed. Try legacy method. } #endif bool haveCABootPlist = false; bool quietBootMode = true; void *fileLoadBuffer = (void *)kLoadAddr; char bootFile[256]; char rootUUID[37]; char * kernelFlags = NULL; const char * val; int length = 0; int kernelFlagsLength = 0; bootFile[0] = '\0'; rootUUID[0] = '\0'; #if PRE_LINKED_KERNEL_SUPPORT bool mayUseKernelCache = false; long flags, cachetime; #endif initPlatform(biosdev); // Passing on the boot drive. #if DEBUG_STATE_ENABLED // Don't switch graphics mode / show boot logo when DEBUG is set to 1. printf("\ngArchCPUType (CPU): %s\n", (gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"); sleep(3); // Silent sleep. #else showBootLogo(); #endif // A bit ugly maybe, but this will be changed sometime soon. while (readKeyboardStatus()) { int key = (bgetc() & 0xff); if ((key |= 0x20) == 'r') { gPlatform.BootRecoveryHD = true; } } initPartitionChain(); #define loadCABootPlist() loadSystemConfig(&bootInfo->bootConfig) // Loading: /Library/Preferences/SystemConfiguration/com.apple.Boot.plist // TODO: Check if everything works <i>without</i> having this plist. if (loadCABootPlist() == STATE_SUCCESS) { _BOOT_DEBUG_DUMP("com.apple.Boot.plist located.\n"); // Load successful. Change state accordantly. haveCABootPlist = true; // Checked <i>before</i> calling key functions. // Check the value of <key>Kernel Flags</key> for stuff we are interested in. // Note: We need to know about: arch= and the boot flags: -s, -v, -f and -x if (getValueForKey(kKernelFlagsKey, &val, &kernelFlagsLength, &bootInfo->bootConfig)) { // "Kernel Flags" key found. Check length to see if we have anything to work with. if (kernelFlagsLength) { kernelFlagsLength++; // Yes. Allocate memory for it and copy the kernel flags into it. kernelFlags = malloc(kernelFlagsLength); strlcpy(kernelFlags, val, kernelFlagsLength); // Is 'arch=<i386/x86_64>' specified as kernel flag? if (getValueForBootKey(kernelFlags, "arch", &val, &length)) // && len >= 4) { gArchCPUType = (strncmp(val, "x86_64", 6) == 0) ? CPU_TYPE_X86_64 : CPU_TYPE_I386; _BOOT_DEBUG_DUMP("gArchCPUType (c.a.B.plist): %s\n", (gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"); } // Check for -v (verbose) and -s (single user mode) flags. gVerboseMode = getValueForBootKey(kernelFlags, kVerboseModeFlag, &val, &length) || getValueForBootKey(kernelFlags, kSingleUserModeFlag, &val, &length); if (gVerboseMode) { #if DEBUG_BOOT == false setVideoMode(VGA_TEXT_MODE); #endif } // Check for -x (safe) and -f (flush cache) flags. if (getValueForBootKey(kernelFlags, kSafeModeFlag, &val, &length) || getValueForBootKey(kernelFlags, kIgnoreCachesFlag, &val, &length)) { gBootMode = kBootModeSafe; } // Is 'boot-uuid=<value>' specified as kernel flag? if (getValueForBootKey(kernelFlags, kBootUUIDKey, &val, &length) && length == 36) { _BOOT_DEBUG_DUMP("Target boot-uuid=<%s>\n", val); // Yes. Copy its value into rootUUID. strlcpy(rootUUID, val, 37); } /* else { strlcpy(rootUUID, "3453E0E5-017B-38AD-A0AA-D0BBD8565D6", 37); _BOOT_DEBUG_DUMP("Target boot-uuid=<%s>\n", rootUUID); } */ } } #if PRE_LINKED_KERNEL_SUPPORT /* Look for 'Kernel Cache' key. */ if (getValueForKey(kKernelCacheKey, &val, &length, &bootInfo->bootConfig)) { _BOOT_DEBUG_DUMP("Kernel Cache set to: %s\n", val); // Key found. Check if the given filepath/name exists. if (length && GetFileInfo(NULL, val, &flags, &cachetime) == 0) { // File located. Init kernelCacheFile so that we can use it as boot file. gPlatform.KernelCachePath = strdup(val); // Set flag to inform the load process to skip parts of the code. gPlatform.KernelCacheSpecified = true; _BOOT_DEBUG_DUMP("kernelcache file found.\n"); } _BOOT_DEBUG_ELSE_DUMP("Error: kernelcache file not found.\n"); } // _BOOT_DEBUG_ELSE_DUMP("No 'Kernel Cache' key given.\n"); #endif /* Enable touching of a single BIOS device by setting 'Scan Single Drive' to yes. if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) { gScanSingleDrive = true; } */ } else { _BOOT_DEBUG_DUMP("No com.apple.Boot.plist found.\n"); } // Was a target drive (per UUID) specified in com.apple.Boot.plist? if (rootUUID[0] == '\0') { _BOOT_DEBUG_DUMP("No UUID specified in com.apple.Boot.plist\n"); // No, so are we booting from a System Volume? if (gPlatform.BootVolume->flags & kBVFlagSystemVolume) { _BOOT_DEBUG_DUMP("Booting from a System Volume, getting UUID.\n"); // Yes, then let's get the UUID. if (HFSGetUUID(gPlatform.BootVolume, rootUUID) == STATE_SUCCESS) { _BOOT_DEBUG_DUMP("Success [%s]\n", rootUUID); } } else // Booting from USB-stick or SDboot media. { _BOOT_DEBUG_DUMP("Booting from a Non System Volume, getting UUID.\n"); // Get target System Volume and UUID in one go. BVRef rootVolume = getTargetRootVolume(rootUUID); if (rootVolume) { _BOOT_DEBUG_DUMP("Success [%s]\n", rootUUID); gPlatform.RootVolume = rootVolume; } } // This should never happen, but just to be sure. if (rootUUID[0] == '\0') { _BOOT_DEBUG_DUMP("Failed to get UUID for System Volume.\n"); if (!gVerboseMode) { // Force verbose mode when we didn't find a UUID, so // that people see what is going on in times of trouble. gVerboseMode = true; } } } /* * At this stage we know exactly what boot mode we're in, and which disk to boot from * any of which may or may not have been set/changed (in com.apple.Boot.plist) into a * non-default system setting and thus is this the place to update our EFI tree. */ updateEFITree(rootUUID); if (haveCABootPlist) // Check boolean before doing more time consuming tasks. { if (getBoolForKey(kQuietBootKey, &quietBootMode, &bootInfo->bootConfig) && !quietBootMode) { gBootMode = kBootModeNormal; // Reversed from: gBootMode |= kBootModeQuiet; } } // Parse args, load and start kernel. while (1) { // Initialize globals. sysConfigValid = 0; gErrors = 0; int retStatus = -1; getAndProcessBootArguments(kernelFlags); // Initialize bootFile (defaults to: mach_kernel). strcpy(bootFile, bootInfo->bootFile); #if PRE_LINKED_KERNEL_SUPPORT _BOOT_DEBUG_DUMP("gBootMode = %d\n", gBootMode); // Preliminary checks to prevent us from doing useless things. mayUseKernelCache = ((gBootMode & kBootModeSafe) == 0); _BOOT_DEBUG_DUMP("mayUseKernelCache = %s\n", mayUseKernelCache ? "true" : "false"); /* * A pre-linked kernel, or kernelcache, requires you to have all essential kexts for your * configuration, including FakeSMC.kext in: /System/Library/Extensions/ * Not in /Extra/Extensions/ because this directory will be ignored, completely when a * pre-linked kernel or kernelcache is used! * * Note: Not following this word of advise will render your system incapable of booting! */ if (mayUseKernelCache == false) { _BOOT_DEBUG_DUMP("Warning: kernelcache will be ignored!\n"); // True when 'Kernel Cache' is set in com.apple.Boot.plist if (gPlatform.KernelCacheSpecified == true) { sprintf(bootFile, "%s", bootInfo->bootFile); } } else { // True when 'Kernel Cache' is set in com.apple.Boot.plist if (gPlatform.KernelCacheSpecified == true) { _BOOT_DEBUG_DUMP("kernelcache: %s\n", gPlatform.KernelCachePath); /* * Starting with Lion, we can take a shortcut by simply pointing * the 'bootFile' to the kernel cache and we are done. */ sprintf(bootFile, "%s", gPlatform.KernelCachePath); } /* * We might have been fired up from a USB thumbdrive (kickstart boot) and * thus we have to check the kernel cache path first (might not be there). */ else if (GetFileInfo(NULL, gPlatform.KernelCachePath, &flags, &cachetime) == 0) { #if ((MAKE_TARGET_OS & LION) == LION) // Also for Mountain Lion, which has bit 2 set like Lion. _BOOT_DEBUG_DUMP("Checking for kernelcache...\n"); if (GetFileInfo(gPlatform.KernelCachePath, (char *)kKernelCache, &flags, &cachetime) == 0) { sprintf(bootFile, "%s/%s", gPlatform.KernelCachePath, kKernelCache); _BOOT_DEBUG_DUMP("Kernelcache located.\n"); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the kernelcache. Will load: %s!\n", bootInfo->bootFile); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the kernelcache (directory)!\n"); } #else // Not for (Mountain) Lion, go easy with the Snow Leopard. static char preLinkedKernelPath[128]; static char adler32Key[PLATFORM_NAME_LEN + ROOT_PATH_LEN]; unsigned long adler32 = 0; preLinkedKernelPath[0] = '\0'; _BOOT_DEBUG_DUMP("Checking for pre-linked kernel...\n"); // Zero out platform info (name and kernel root path). bzero(adler32Key, sizeof(adler32Key)); // Construct key for the pre-linked kernel checksum (generated by adler32). sprintf(adler32Key, gPlatform.ModelID); sprintf(adler32Key + PLATFORM_NAME_LEN, "%s", BOOT_DEVICE_PATH); sprintf(adler32Key + (PLATFORM_NAME_LEN + 38), "%s", bootInfo->bootFile); adler32 = Adler32((unsigned char *)adler32Key, sizeof(adler32Key)); _BOOT_DEBUG_DUMP("adler32: %08X\n", adler32); // Create path to pre-linked kernel. sprintf(preLinkedKernelPath, "%s/%s_%s.%08lX", gPlatform.KernelCachePath, kKernelCache, ((gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"), adler32); // Check if this file exists. if ((GetFileInfo(NULL, preLinkedKernelPath, &flags, &cachetime) == 0) && ((flags & kFileTypeMask) == kFileTypeFlat)) { _BOOT_DEBUG_DUMP("Pre-linked kernel cache located!\nLoading pre-linked kernel: %s\n", preLinkedKernelPath); // Returns -1 on error, or the actual filesize. if (LoadFile((const char *)preLinkedKernelPath)) { retStatus = 1; fileLoadBuffer = (void *)kLoadAddr; bootFile[0] = 0; } _BOOT_DEBUG_ELSE_DUMP("Failed to load the pre-linked kernel. Will load: %s!\n", bootInfo->bootFile); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the pre-linked kernel!\n"); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the cache directory!\n"); }