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];
static void Main(ClientInterfacePtr ciPtr)
{
long ret;
+ int trycache;
+ long flags, cachetime, time;
ret = InitEverything(ciPtr);
if (ret != 0) Exit();
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);
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);
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);
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);
static long GetBootPaths(void)
{
long ret, cnt, cnt2, cnt3, cnt4, size, partNum, bootplen, bsdplen;
+ unsigned long adler32;
char *filePath, *buffer;
if (gBootSourceNumber == -1) {
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;
}
// 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;
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++;