X-Git-Url: https://git.saurik.com/apple/bootx.git/blobdiff_plain/71019aa06eea45d05e1aa2efb1835c3ac831548e..b1faa321993abbedc0d50f45e8e7308549eead26:/bootx.tproj/sl.subproj/main.c diff --git a/bootx.tproj/sl.subproj/main.c b/bootx.tproj/sl.subproj/main.c index f4b8fae..e06392c 100644 --- a/bootx.tproj/sl.subproj/main.c +++ b/bootx.tproj/sl.subproj/main.c @@ -65,9 +65,13 @@ long gBootSourceNumberMax; long gBootMode = kBootModeNormal; long gBootDeviceType; long gBootFileType; +char gHaveKernelCache = 0; char gBootDevice[256]; char gBootFile[256]; -char gRootDir[256]; +static char gBootKernelCacheFile[512]; +static char gExtensionsSpec[4096]; +static char gCacheNameAdler[64 + sizeof(gBootFile)]; +static char *gPlatformName = gCacheNameAdler; char gTempStr[4096]; @@ -115,6 +119,8 @@ static void Start(void *unused1, void *unused2, ClientInterfacePtr ciPtr) static void Main(ClientInterfacePtr ciPtr) { long ret; + int trycache; + long flags, cachetime, time; ret = InitEverything(ciPtr); if (ret != 0) Exit(); @@ -126,18 +132,53 @@ static void Main(ClientInterfacePtr ciPtr) DrawSplashScreen(0); while (ret == 0) { + trycache = (0 == (gBootMode & kBootModeSafe)) + && (gBootKernelCacheFile[0] != 0); + + if (trycache && (gBootFileType == kBlockDeviceType)) do { + + // if we haven't found the kernel yet, don't use the cache + ret = GetFileInfo(NULL, gBootFile, &flags, &time); + if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) { + trycache = 0; + break; + } + ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime); + if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat) + || (cachetime < time)) { + trycache = 0; + break; + } + ret = GetFileInfo(gExtensionsSpec, "Extensions", &flags, &time); + if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) + && (cachetime < time)) { + trycache = 0; + break; + } + } while (0); + + if (trycache) { + ret = LoadFile(gBootKernelCacheFile); + if (ret != -1) { + ret = DecodeKernel(); + if (ret != -1) break; + } + } ret = LoadFile(gBootFile); + if (ret != -1) + ret = DecodeKernel(); if (ret != -1) break; ret = GetBootPaths(); if (ret != 0) FailToBoot(2); } - ret = DecodeKernel(); if (ret != 0) FailToBoot(3); - ret = LoadDrivers(gRootDir); - if (ret != 0) FailToBoot(4); + if (!gHaveKernelCache) { + ret = LoadDrivers(gExtensionsSpec); + if (ret != 0) FailToBoot(4); + } DrawSplashScreen(1); @@ -155,6 +196,8 @@ static long InitEverything(ClientInterfacePtr ciPtr) long ret, mem_base, mem_base2, size; CICell keyboardPH; char name[32], securityMode[33]; + long length; + char *compatible; // Init the OF Client Interface. ret = InitCI(ciPtr); @@ -197,6 +240,11 @@ static long InitEverything(ClientInterfacePtr ciPtr) return -1; } + // Get first element of root's compatible property. + ret = GetPackageProperty(Peer(0), "compatible", &compatible, &length); + if (ret != -1) + strcpy(gPlatformName, compatible); + // Get stdout's IH, so that the boot display can be found. ret = GetProp(gChosenPH, "stdout", (char *)&gStdOutIH, 4); if (ret == 4) gStdOutPH = InstanceToPackage(gStdOutIH); @@ -334,11 +382,34 @@ long ThinFatBinary(void **binary, unsigned long *length) return ret; } - static long DecodeKernel(void) { void *binary = (void *)kLoadAddr; long ret; + compressed_kernel_header * kernel_header = (compressed_kernel_header *) kLoadAddr; + u_int32_t size; + + if (kernel_header->signature == 'comp') { + if (kernel_header->compress_type != 'lzss') + return -1; + if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) + return -1; + if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) + return -1; + + binary = AllocateBootXMemory(kernel_header->uncompressed_size); + + size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0], kernel_header->compressed_size); + if (kernel_header->uncompressed_size != size) { + printf("size mismatch from lzss %x\n", size); + return -1; + } + if (kernel_header->adler32 != + Alder32(binary, kernel_header->uncompressed_size)) { + printf("adler mismatch\n"); + return -1; + } + } ThinFatBinary(&binary, 0); @@ -740,6 +811,7 @@ static long TestForKey(long key) static long GetBootPaths(void) { long ret, cnt, cnt2, cnt3, cnt4, size, partNum, bootplen, bsdplen; + unsigned long adler32; char *filePath, *buffer; if (gBootSourceNumber == -1) { @@ -870,8 +942,18 @@ static long GetBootPaths(void) strncpy(gBootFile, gBootDevice, cnt + 1); sprintf(gBootFile + cnt + 1, "%d,%s\\mach_kernel", partNum, ((gBootSourceNumber & 1) ? "" : "\\")); + + // and the cache file name + + bzero(gCacheNameAdler + 64, sizeof(gBootFile)); + strcpy(gCacheNameAdler + 64, gBootFile); + adler32 = Alder32(gCacheNameAdler, sizeof(gCacheNameAdler)); + + strncpy(gBootKernelCacheFile, gBootDevice, cnt + 1); + sprintf(gBootKernelCacheFile + cnt + 1, + "%d,\\System\\Library\\Caches\\com.apple.kernelcaches\\kernelcache.%08lX", partNum, adler32); break; - + default: printf("Failed to infer Boot Device Type.\n"); return -1; @@ -880,10 +962,10 @@ static long GetBootPaths(void) } // Figure out the root dir. - ret = ConvertFileSpec(gBootFile, gRootDir, &filePath); + ret = ConvertFileSpec(gBootFile, gExtensionsSpec, &filePath); if (ret == -1) return -1; - strcat(gRootDir, ","); + strcat(gExtensionsSpec, ","); // Add in any extra path to gRootDir. cnt = 0; @@ -892,12 +974,20 @@ static long GetBootPaths(void) if (cnt != 0) { for (cnt2 = cnt - 1; cnt2 >= 0; cnt2--) { if (filePath[cnt2] == '\\') { - strncat(gRootDir, filePath, cnt2 + 1); + strncat(gExtensionsSpec, filePath, cnt2 + 1); break; } } } - + + // Figure out the extensions dir. + if (gBootFileType == kBlockDeviceType) { + cnt = strlen(gExtensionsSpec); + if ((cnt > 2) && (gExtensionsSpec[cnt-1] == '\\') && (gExtensionsSpec[cnt-2] == '\\')) + cnt--; + strcpy(gExtensionsSpec + cnt, "System\\Library\\"); + } + SetProp(gChosenPH, "rootpath", gBootFile, strlen(gBootFile) + 1); gBootSourceNumber++;