]> git.saurik.com Git - apple/boot.git/blobdiff - i386/boot2/boot.c
boot-132.tar.gz
[apple/boot.git] / i386 / boot2 / boot.c
index 94aa760e7da717b65bd0426d449549bc20176f02..d935082a327bfd18bea076a388a957a41c9d5448 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Portions Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights
  * Reserved.  This file contains Original Code and/or Modifications of
  * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License").  You may not use this file
+ * Source License Version 2.0 (the "License").  You may not use this file
  * except in compliance with the License.  Please obtain a copy of the
  * License at http://www.apple.com/publicsource and read it before using
  * this file.
  * Completely reworked by Sam Streeper (sam_s@NeXT.com)
  * Reworked again by Curtis Galloway (galloway@NeXT.com)
  */
-#include "libsa.h"
-#include "memory.h"
-#include "saio.h"
-#include "libsaio.h"
-#include "kernBootStruct.h"
+
+
 #include "boot.h"
-#include "drivers.h"
-#include "nbp.h"
+#include "bootstruct.h"
+#include "sl.h"
+#include "libsa.h"
 
-/*
- * True if using default.table
- */
-static BOOL useDefaultConfig;
 
-/*
- * Name of the kernel image file to load.
- * This is specified in the config file, or may be
- * overridden by the user at the boot prompt.
- */
-static char gKernelName[BOOT_STRING_LEN];
+long gBootMode; /* defaults to 0 == kBootModeNormal */
+BOOL gOverrideKernel;
+static char gBootKernelCacheFile[512];
+static char gCacheNameAdler[64 + 256];
+char *gPlatformName = gCacheNameAdler;
+char gRootDevice[512];
+char gMKextName[512];
+BVRef gBootVolume;
 
-/*
- * The user asked for boot graphics.
- */
-static BOOL gWantBootGraphics = NO;
+static
+unsigned long Adler32(unsigned char *buffer, long length);
 
-/*
- * The device that the booter was loaded from.
- */
-int gBootDev;
-
-extern char * gFilename;
-extern BOOL   sysConfigValid;
-extern char   bootPrompt[];    // In prompt.c
-extern BOOL   errors;
-extern BOOL   verbose_mode;
-extern BOOL   gSilentBoot;
-
-#if MULTIPLE_DEFAULTS
-char * default_names[] = {
-    "$LBL",
-};
-#define NUM_DEFAULT_NAMES   (sizeof(default_names)/sizeof(char *))
-int current_default = 0;
-#else
-#define DEFAULT_NAME    "$LBL"
-#endif
+
+static BOOL gUnloadPXEOnExit = 0;
 
 /*
- * Prototypes.
+ * How long to wait (in seconds) to load the
+ * kernel after displaying the "boot:" prompt.
  */
-static void getBootString();
+#define kBootErrorTimeout 5
 
 /*
- * Message/Error logging macros.
+ * Default path to kernel cache file
  */
-#define PRINT(x)        { printf x }
-
-#ifdef  DEBUG
-#define DPRINT(x)       { printf x; }
-#define DSPRINT(x)      { printf x; sleep(2); }
-#else
-#define DPRINT(x)
-#define DSPRINT(x)
-#endif
+#define kDefaultCachePath "/System/Library/Caches/com.apple.kernelcaches/kernelcache"
 
 //==========================================================================
 // Zero the BSS.
 
-static void
-zeroBSS()
+static void zeroBSS()
 {
     extern char _DATA__bss__begin, _DATA__bss__end;
     extern char _DATA__common__begin, _DATA__common__end;
 
     bzero( &_DATA__bss__begin,
            (&_DATA__bss__end - &_DATA__bss__begin) );
-    
+
     bzero( &_DATA__common__begin, 
            (&_DATA__common__end - &_DATA__common__begin) );
 }
 
 //==========================================================================
-// execKernel - Load the kernel image file and jump to its entry point.
+// Malloc error function
 
-static int
-execKernel(int fd, int installMode)
+static void malloc_error(char *addr, size_t size)
+{
+    printf("\nMemory allocation error (0x%x, 0x%x)\n",
+           (unsigned)addr, (unsigned)size);
+    asm volatile ("hlt");
+}
+
+//==========================================================================
+// execKernel - Load the kernel image (mach-o) and jump to its entry point.
+
+static int ExecKernel(void *binary)
 {
-    register KERNBOOTSTRUCT * kbp = kernBootStruct;
-    register char *           src = gFilename;
-    register char *           dst = kbp->boot_file;
-    char *                    val;
-    static struct mach_header head;
     entry_t                   kernelEntry;
-    int                       ret, size;
-#ifdef DISABLED
-    char *                    linkerPath;
-    int                       loadDrivers;
-#endif
+    int                       ret;
+    BOOL                      bootGraphics;
+
+    bootArgs->kaddr = bootArgs->ksize = 0;
 
-    /* Copy the space/tab delimited word pointed by src (gFilename) to
-     * kbp->boot_file.
-     */ 
-    while (*src && (*src != ' ' && *src != '\t'))
-        *dst++ = *src++;
-    *dst = 0;
-
-    verbose("Loading %s\n", kbp->boot_file);
-
-    /* perform the actual load */
-    kbp->kaddr = kbp->ksize = 0;
-    ret = loadprog(kbp->kernDev,
-                   fd,
-                   &head,
-                   &kernelEntry,
-                   (char **) &kbp->kaddr,
-                   &kbp->ksize);
-    close(fd);
+    ret = DecodeKernel(binary,
+                       &kernelEntry,
+                       (char **) &bootArgs->kaddr,
+                       (int *)&bootArgs->ksize );
 
     if ( ret != 0 )
         return ret;
 
-    /* Clear memory that might be used for loaded drivers
-     * because the standalone linker doesn't zero
-     * memory that is used later for BSS in the drivers.
-     */
-    {
-        long addr = kbp->kaddr + kbp->ksize;
-        bzero((char *)addr, RLD_MEM_ADDR - addr);
-    }
+    // Reserve space for boot args
+    reserveKernBootStruct();
 
-    clearActivityIndicator();
-    printf("\n");
-
-    if ((getValueForKey("Kernel Flags", &val, &size)) && size) {
-        int oldlen, len1;
-        char * cp = kbp->bootString;
-        oldlen = len1 = strlen(cp);
-
-        // move out the user string
-        for(; len1 >= 0; len1--)
-            cp[size + len1] = cp[len1 - 1];
-        strncpy(cp,val,size);
-        if (oldlen) cp[strlen(cp)] = ' ';
-    }
+    // Load boot drivers from the specifed root path.
 
-    if (errors) {
-        printf("Errors encountered while starting up the computer.\n");
-        printf("Pausing %d seconds...\n", BOOT_TIMEOUT);
-        sleep(BOOT_TIMEOUT);
+    if (!gHaveKernelCache) {
+          LoadDrivers("/");
     }
 
-    message("Starting Darwin Intel", 0);
-    
-    if (kbp->eisaConfigFunctions)
-        kbp->first_addr0 = EISA_CONFIG_ADDR +
-            (kbp->eisaConfigFunctions * sizeof(EISA_func_info_t));
-
     clearActivityIndicator();
 
-    turnOffFloppy();
-
-    if ( getBoolForKey("APM") )
-    {
-        if ( APMPresent() ) APMConnect32();
+    if (gErrors) {
+        printf("Errors encountered while starting up the computer.\n");
+        printf("Pausing %d seconds...\n", kBootErrorTimeout);
+        sleep(kBootErrorTimeout);
     }
 
-       // Cleanup the PXE base code.
+    printf("Starting Darwin/x86");
 
-       if ( gBootDev == kBootDevNetwork )
-    {
+    // Cleanup the PXE base code.
+
+    if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) {
                if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess )
         {
-               printf("nbpUnloadBaseCode error %d\n", (int) ret); sleep(2);
+               printf("nbpUnloadBaseCode error %d\n", (int) ret);
+            sleep(2);
         }
     }
 
-    // Switch to graphics mode just before starting the kernel.
+    // Unless Boot Graphics = No, Always switch to graphics mode
+    // just before starting the kernel.
 
-    if ( gWantBootGraphics )
-    {
-        setMode(GRAPHICS_MODE);
+    if (!getBoolForKey(kBootGraphicsKey, &bootGraphics)) {
+        bootGraphics = YES;
     }
 
+    if (bootGraphics) {
+        if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
+            // If we were in text mode, switch to graphics mode.
+            // This will draw the boot graphics unless we are in
+            // verbose mode.
+            setVideoMode( GRAPHICS_MODE );
+        } else {
+            // If we were already in graphics mode, clear the screen.
+            drawBootGraphics();
+        }
+    } else {
+        // Always set text mode to initialize video fields
+        // in the boot args structure.
+        setVideoMode( VGA_TEXT_MODE );
+        setCursorType( kCursorTypeHidden );
+    }
+
+    finalizeBootStruct();
+
     // Jump to kernel's entry point. There's no going back now.
 
-    startprog(kernelEntry);
+    startprog( kernelEntry, bootArgs );
 
     // Not reached
 
@@ -242,345 +191,259 @@ execKernel(int fd, int installMode)
 }
 
 //==========================================================================
-// Scan and record the system's PCI bus information.
-//
+// Scan and record the system's hardware information.
 
 static void scanHardware()
 {
-extern int  ReadPCIBusInfo(PCI_bus_info_t *pp);
-extern void PCI_Bus_Init(PCI_bus_info_t *);
-    
-    KERNBOOTSTRUCT * kbp = KERNSTRUCT_ADDR;
+    extern int  ReadPCIBusInfo(PCI_bus_info_t *);
+    extern void PCI_Bus_Init(PCI_bus_info_t *);
 
-    ReadPCIBusInfo( &kbp->pciInfo );
-    PCI_Bus_Init( &kbp->pciInfo );
+    ReadPCIBusInfo( &bootInfo->pciInfo );
+    
+    //
+    // Initialize PCI matching support in the booter.
+    // Not used, commented out to minimize code size.
+    //
+    // PCI_Bus_Init( &bootInfo->pciInfo );
 }
 
 //==========================================================================
-// The 'main' function for the booter. This function is called by the
-// assembly routine init(), which is in turn called by boot1 or by
-// NBP.
+// The 'main' function for the booter. Called by boot0 when booting
+// from a block device, or by the network booter.
 //
 // arguments:
-//   bootdev - Value passed from boot1/NBP to specify the device
-//             that the booter was loaded from. See boot.h for the list
-//             of allowable values.
+//   biosdev - Value passed from boot1/NBP to specify the device
+//             that the booter was loaded from.
 //
-// If bootdev is kBootDevNetwork, then this function will return if
+// If biosdev is kBIOSDevNetwork, then this function will return if
 // booting was unsuccessful. This allows the PXE firmware to try the
-// next bootable device on its list. If bootdev is not kBootDevNetwork,
-// this function will not return control back to the caller.
+// next boot device on its list.
+
+#define DLOG(x) outb(0x80, (x))
 
-void
-boot(int bootdev)
+void boot(int biosdev)
 {
-    register KERNBOOTSTRUCT * kbp = kernBootStruct;
-    int      fd, size;
-    char *   val;
-    int      installMode = 0;
+    int      status;
+    char     *bootFile;
+    unsigned long adler32;
+    BOOL     quiet;
+    BOOL     firstRun = YES;
+    BVRef    bvChain;
 
     zeroBSS();
 
-    // Enable A20 gate to be able to access memory above 1 MB.
+    // Initialize malloc
+    malloc_init(0, 0, 0, malloc_error);
+
+    // Enable A20 gate before accessing memory above 1Mb.
 
     enableA20();
 
-    // Remember the device that the booter was loaded from.
+    // Set reminder to unload the PXE base code. Neglect to unload
+    // the base code will result in a hang or kernel panic.
+
+    gUnloadPXEOnExit = 1;
 
-    gBootDev = bootdev;
+    // Record the device that the booter was loaded from.
+
+    gBIOSDev = biosdev & kBIOSDevMask;
 
     // Initialize boot info structure.
 
-    initKernBootStruct();
+    initKernBootStruct( gBIOSDev );
 
     // Setup VGA text mode.
+    // Not sure if it is safe to call setVideoMode() before the
+    // config table has been loaded. Call video_mode() instead.
 
-    setMode(TEXT_MODE);
-
-    // Initialize the malloc area to the top of conventional memory.
+#if DEBUG
+    printf("before video_mode\n");
+#endif
+    video_mode( 2 );  // 80x25 mono text mode.
+#if DEBUG
+    printf("after video_mode\n");
+#endif
 
-    malloc_init( (char *) ZALLOC_ADDR,
-                 (kbp->convmem * 1024) - ZALLOC_ADDR,
-                 ZALLOC_NODES );
+    // Check to see that this hardware is supported.
+    status = checkForSupportedHardware();
+    if (status != 0) {
+        stop("This hardware configuration is not supported by Darwin/x86. (%d)", status);
+    }
 
     // Scan hardware configuration.
-
     scanHardware();
 
-    // Display initial banner.
+    // First get info for boot volume.
+    bvChain = scanBootVolumes(gBIOSDev, 0);
+
+    // Record default boot device.
+    gBootVolume = selectBootVolume(bvChain);
+    bootInfo->kernDev = MAKEKERNDEV(gBIOSDev,
+                                    BIOS_DEV_UNIT(gBootVolume),
+                                    gBootVolume->part_no );
 
-    printf( bootPrompt, kbp->convmem, kbp->extmem );
-    printf( "Darwin Intel will start up in %d seconds, or you can:\n"
-            "  Type -v and press Return to start up Darwin Intel with "
-              "diagnostic messages\n"
-            "  Type ? and press Return to learn about advanced startup "
-              "options\n"
-            "  Type any other character to stop Darwin Intel from "
-              "starting up automatically\n",
-            BOOT_TIMEOUT );
+    // Load default config file from boot device.
+    status = loadSystemConfig(0, 0);
+
+    if ( getBoolForKey( kQuietBootKey, &quiet ) && quiet ) {
+        gBootMode |= kBootModeQuiet;
+    }
 
     // Parse args, load and start kernel.
 
     while (1)
     {
-        // Initialize globals.
+        const char *val;
+        int len;
+        int trycache;
+        long flags, cachetime, kerneltime, exttime;
+        int ret = -1;
+        void *binary = (void *)kLoadAddr;
 
-        sysConfigValid   = 0;
-        useDefaultConfig = 0;
-        errors           = 0;
+        // Initialize globals.
 
-        // Make sure we are in VGA text mode.
+        sysConfigValid = 0;
+        gErrors        = 0;
 
-        setMode(TEXT_MODE);
+        status = getBootOptions(firstRun);
+        firstRun = NO;
+        if (status == -1) continue;
 
-        // Set up kbp->kernDev to reflect the boot device.
+        status = processBootOptions();
+        if ( status ==  1 ) break;
+        if ( status == -1 ) continue;
 
-        if ( bootdev == kBootDevHardDisk )
-        {
-            if (kbp->numIDEs > 0)
-            {
-                kbp->kernDev = DEV_HD;
-            }
-            else
-            {
-                kbp->kernDev = DEV_SD;
-            }
-        }
-        else if ( bootdev == kBootDevFloppyDisk )
-        {
-            kbp->kernDev = DEV_FLOPPY;
-        }
-        else
-        {
-            kbp->kernDev = DEV_EN;
-        }
-        flushdev();
-
-#if 0   // XXX - $LBL
-#if MULTIPLE_DEFAULTS
-        strcpy(gKernelName, default_names[current_default]);
-        if (++current_default == NUM_DEFAULT_NAMES)
-            current_default = 0;
-#else
-        strcpy(gKernelName, DEFAULT_NAME);
-#endif
-#endif
+        // Found and loaded a config file. Proceed with boot.
 
-        // Display boot prompt and get user supplied boot string.
 
-        getBootString();
+        // Reset cache name.
+        bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
 
-        if ( bootdev != kBootDevNetwork )
-        {
-            // To force loading config file off same device as kernel,
-            // open kernel file to force device change if necessary.
+        sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile);
 
-            fd = open(gKernelName, 0);
-            if (fd >= 0)
-                close(fd);
-        }
+        adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
 
-        if ( sysConfigValid == 0 )
-        {
-            val = 0;
-            getValueForBootKey(kbp->bootString, 
-                               "config", &val, &size);
-
-            DSPRINT(("sys config was not valid trying alt\n"));
-            useDefaultConfig = loadSystemConfig(val, size);
-            
-            if ( sysConfigValid == 0 )
-            {
-                DSPRINT(("sys config is not valid\n"));
-                if (kbp->kernDev == DEV_EN)
-                    break;      // return control back to PXE
-                else
-                    continue;   // keep looping
-            }
+        if (getValueForKey(kKernelCacheKey, &val, &len) == YES) {
+            strlcpy(gBootKernelCacheFile, val, len+1);
+        } else {
+            sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePath, adler32);
         }
 
-        // Found and loaded a config file. Proceed with boot.
+        // Check for cache file.
 
-        gWantBootGraphics = getBoolForKey("Boot Graphics");
-        gSilentBoot       = getBoolForKey("Silent Boot");
+        trycache = (((gBootMode & kBootModeSafe) == 0) &&
+                    (gOverrideKernel == NO) &&
+                    (gBootFileType == kBlockDeviceType) &&
+                    (gMKextName[0] == '\0') &&
+                    (gBootKernelCacheFile[0] != '\0'));
 
-        message("Loading Darwin Intel", 0);
+        printf("Loading Darwin/x86\n");
 
-        if ( (fd = openfile(gKernelName, 0)) >= 0 )
-        {
-            DSPRINT(("calling exec kernel\n"));
-            execKernel(fd, installMode);
+        if (trycache) do {
+      
+            // if we haven't found the kernel yet, don't use the cache
+            ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
+            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
+                trycache = 0;
+                break;
+            }
+            ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
+            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
+                || (cachetime < kerneltime)) {
+                trycache = 0;
+                break;
+            }
+            ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
+            if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
+                && (cachetime < exttime)) {
+                trycache = 0;
+                break;
+            }
+            if (kerneltime > exttime) {
+                exttime = kerneltime;
+            }
+            if (cachetime != (exttime + 1)) {
+                trycache = 0;
+                break;
+            }
+        } while (0);
+
+        do {
+            if (trycache) {
+                bootFile = gBootKernelCacheFile;
+                verbose("Loading kernel cache %s\n", bootFile);
+                ret = LoadFile(bootFile);
+                binary = (void *)kLoadAddr;
+                if (ret >= 0) {
+                    break;
+                }
+            }
+            bootFile = bootInfo->bootFile;
+            verbose("Loading kernel %s\n", bootFile);
+            ret = LoadThinFatFile(bootFile, &binary);
+        } while (0);
+
+        clearActivityIndicator();
+#if DEBUG
+        printf("Pausing...");
+        sleep(8);
+#endif
 
-            // If execKernel() returns, kernel load failed.
-        }
-        else
-        {
-            error("Can't find %s\n", gKernelName);
+        if (ret < 0) {
+            error("Can't find %s\n", bootFile);
 
-            if ( bootdev == kBootDevFloppyDisk )
-            {
-                // floppy in drive, but failed to load kernel.
-                bootdev = kBootDevHardDisk;
-                message("Couldn't start up the computer using this "
-                        "floppy disk.", 0);
-            }
-            else if ( bootdev == kBootDevNetwork )
+            if ( gBootFileType == kNetworkDeviceType )
             {
-                break;   // Return control back to PXE.
+                // Return control back to PXE. Don't unload PXE base code.
+                gUnloadPXEOnExit = 0;
+                break;
             }
+        } else {
+            /* Won't return if successful. */
+            ret = ExecKernel(binary);
         }
-    } /* while(1) */
-}
-
-//==========================================================================
-// Skip spaces/tabs characters.
 
-static inline void
-skipblanks(char ** cp) 
-{
-    while ( **(cp) == ' ' || **(cp) == '\t' )
-        ++(*cp);
-}
-
-//==========================================================================
-// Load the help file and display the file contents on the screen.
-
-static void showHelp()
-{
-    int    fd;
-    char * help = makeFilePath("BootHelp.txt");
-
-    if ( (fd = open(help, 0)) >= 0 )
-    {
-        char * buffer = malloc( file_size(fd) );
-        read(fd, buffer, file_size(fd) - 1);
-        close(fd);
-        printf("%s", buffer);
-        free(buffer);
+    } /* while(1) */
+    
+    if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
+       nbpUnloadBaseCode();
     }
 }
 
-//==========================================================================
-// Returns 1 if the string pointed by 'cp' contains an user-specified
-// kernel image file name. Used by getBootString() function.
-
-static inline int
-containsKernelName(char * cp)
-{
-    register char c;
-    
-    skipblanks(&cp);
-
-    // Convert everything to lower case.
-
-    c = *cp | 0x20;
-
-    // Must start with a letter or a '/'.
-
-    if ( (c < 'a' || c > 'z') && ( c != '/' ) )
-        return 0;
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5000
+// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
 
-    // Keep consuming characters until we hit a separator.
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
 
-    while ( *cp && (*cp != '=') && (*cp != ' ') && (*cp != '\t') )
-        cp++;
-
-    // Only SPACE or TAB separator is accepted.
-    // Reject everything else.
-
-    if (*cp == '=')
-        return 0;
-
-    return 1;
-}
-
-//==========================================================================
-// Display the "boot:" prompt and copies the user supplied string to
-// kernBootStruct->bootString. The kernel image file name is written
-// to the gKernelName buffer.
-
-static void
-getBootString()
+unsigned long Adler32(unsigned char *buf, long len)
 {
-    char         line[BOOT_STRING_LEN];
-    char *       cp;
-    char *       val;
-    int          count;
-    static int   timeout = BOOT_TIMEOUT;
-
-top:
-    line[0] = '\0';
-    cp      = &line[0];
-
-    /* If there have been problems, don't go on. */
-    if ( errors ) timeout = 0;
-    errors = 0;
-
-    // Print the boot prompt and wait a few seconds for user input.
-
-    printf("\n");
-    count = Gets(line, sizeof(line), timeout, "boot: ", "");
-    flushdev();
-
-    // If something was typed, don't use automatic boot again.
-    // The boot: prompt will not timeout and go away until
-    // the user hits the return key.
-
-    if ( count ) timeout = 0;
-
-    skipblanks(&cp);
-
-    // If user typed '?', then display the usage message.
-
-    if ( *cp == '?' )
-    {
-        showHelp();
-        goto top;
-    }
-
-    // Did the user specify a kernel file name at the boot prompt?
-
-    if ( containsKernelName(cp) == 0 )
-    {
-        // User did not type a kernel image file name on the boot prompt.
-        // This is fine, read the default kernel file name from the
-        // config table.
-
-        printf("\n");
-
-        val = 0;
-        getValueForBootKey(cp, "config", &val, &count);
-
-        useDefaultConfig = loadSystemConfig(val, count);
-
-        if ( !sysConfigValid )
-            goto top;
-
-        // Get the kernel name from the config table file.
-
-        if ( getValueForKey( "Kernel", &val, &count) )
-        {
-            strncpy(gKernelName, val, count);
+    unsigned long s1 = 1; // adler & 0xffff;
+    unsigned long s2 = 0; // (adler >> 16) & 0xffff;
+    unsigned long result;
+    int k;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+            buf += 16;
+            k -= 16;
         }
+        if (k != 0) do {
+            s1 += *buf++;
+            s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
     }
-    else
-    {
-        // Get the kernel name from the user-supplied boot string,
-        // and copy the name to the buffer provided.
-
-        char * namep = gKernelName;
-
-        while ( *cp && !(*cp == ' ' || *cp == '\t') )
-            *namep++ = *cp++;
-
-        *namep = '\0';
-    }
-
-    // Verbose flag specified.
-
-    verbose_mode = getValueForBootKey(cp, "-v", &val, &count);
+    result = (s2 << 16) | s1;
+    return OSSwapHostToBigInt32(result);
+}
 
-    // Save the boot string in kernBootStruct.
 
-    strcpy(kernBootStruct->bootString, cp);
-}