From bba600dda0ea8a76d875db7308f372bfc43f8506 Mon Sep 17 00:00:00 2001
From: Apple <opensource@apple.com>
Date: Tue, 24 Oct 2006 16:22:19 +0000
Subject: [PATCH] boot-132.tar.gz

---
 i386/boot1u/Makefile         |   8 +-
 i386/boot1u/string.c         |   4 +-
 i386/boot2/Makefile          |   9 +-
 i386/boot2/WKdm.h            | 227 +++++++++++++++
 i386/boot2/WKdmDecompress.c  | 285 ++++++++++++++++++
 i386/boot2/boot.c            |  90 +++---
 i386/boot2/boot.h            |  12 +-
 i386/boot2/drivers.c         |  79 ++---
 i386/boot2/graphics.c        |  84 ++++--
 i386/boot2/options.c         | 278 +++++++++++++-----
 i386/cdboot/cdboot.s         |   2 +-
 i386/libsa/Makefile          |   5 +-
 i386/libsa/memory.h          |   8 +-
 i386/libsa/string.c          |  10 +-
 i386/libsa/zalloc.c          |   4 +-
 i386/libsaio/Makefile        |  12 +-
 i386/libsaio/asm.s           |   5 +-
 i386/libsaio/bios.h          |  24 ++
 i386/libsaio/biosfn.c        |  33 ++-
 i386/libsaio/bootstruct.c    | 174 ++++++-----
 i386/libsaio/bootstruct.h    |  85 +++++-
 i386/libsaio/cache.c         |   4 +-
 i386/libsaio/console.c       |  12 +-
 i386/libsaio/device_tree.c   | 539 +++++++++++++++++++++++++++++++++++
 i386/libsaio/device_tree.h   |  61 ++++
 i386/libsaio/disk.c          |  58 ++--
 i386/libsaio/hfs.c           |  41 ++-
 i386/libsaio/hfs.h           |   1 +
 i386/libsaio/hfs_compare.c   |   2 +-
 i386/libsaio/load.c          |   2 +-
 i386/libsaio/md5c.c          | 344 ++++++++++++++++++++++
 i386/libsaio/memory.c        |  24 ++
 i386/libsaio/misc.c          |  44 +++
 i386/libsaio/msdos.c         |  12 +-
 i386/libsaio/nbp.c           |   2 +-
 i386/libsaio/ntfs.c          |   8 +-
 i386/libsaio/saio_internal.h |  10 +-
 i386/libsaio/saio_types.h    |  55 ++++
 i386/libsaio/stringTable.c   |  21 +-
 i386/libsaio/sys.c           |  90 +++++-
 i386/libsaio/ufs.c           |  46 ++-
 i386/libsaio/ufs.h           |   1 +
 i386/libsaio/ufs_byteorder.c |  18 +-
 i386/libsaio/ufs_byteorder.h |   5 +-
 i386/libsaio/vbe.h           |   2 +-
 i386/nasm/Makefile           |   2 +-
 i386/rcz/Makefile            |   2 +-
 i386/strings/BootHelp.txt    |   6 +-
 i386/strings/Makefile        |   2 +-
 i386/testmodule/Makefile     |   2 +-
 i386/util/Makefile           |   2 +-
 51 files changed, 2443 insertions(+), 413 deletions(-)
 create mode 100644 i386/boot2/WKdm.h
 create mode 100644 i386/boot2/WKdmDecompress.c
 create mode 100644 i386/libsaio/device_tree.c
 create mode 100644 i386/libsaio/device_tree.h
 create mode 100644 i386/libsaio/md5c.c

diff --git a/i386/boot1u/Makefile b/i386/boot1u/Makefile
index 0f479ca..36fcd03 100644
--- a/i386/boot1u/Makefile
+++ b/i386/boot1u/Makefile
@@ -1,11 +1,11 @@
 DIR = boot1u
 include ../MakePaths.dir
 
-OPTIM = -Os
+OPTIM = -Os -Oz
 CFLAGS	= $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
           -fno-builtin -DSAIO_INTERNAL_USER -DBOOT1 -static \
 	  -fomit-frame-pointer -mpreferred-stack-boundary=2 \
-	  -fno-align-functions
+	  -fno-align-functions -mno-sse2 -mfpmath=387
 DEFINES=
 CONFIG = hd
 SYMDIR = $(SYMROOT)
@@ -19,7 +19,7 @@ else
   MKDIRS = /bin/mkdir -p
 endif
 AS = as
-LD = ld
+LD = gcc
 LIBS= -L$(SYMDIR) -lsa
 #LIBS= -L$(SYMDIR)
 
@@ -71,7 +71,7 @@ boot1u0: boot1u0.s Makefile $(NASM)
 	$(NASM) boot1u0.s -o $(SYMROOT)/$@
 
 boot1u: $(SYMROOT)/machOconv boot1u0 $(OBJS)
-	$(LD) -static -preload -segaddr __TEXT $(BOOT1UADDR) -segalign 20 \
+	$(LD) -arch i386 -fno-builtin -static -Wl,-preload -Wl,-segaddr,__TEXT,$(BOOT1UADDR) -nostdlib -Wl,-segalign,20 \
 		-o $(SYMROOT)/$(@F).sys $(filter %.o,$^) $(LIBS) -lcc_kext
 	size $(SYMROOT)/$(@F).sys
 	$(SYMROOT)/machOconv $(SYMROOT)/$(@F).sys $(SYMROOT)/$(@F).post
diff --git a/i386/boot1u/string.c b/i386/boot1u/string.c
index 91e1791..4abdb72 100644
--- a/i386/boot1u/string.c
+++ b/i386/boot1u/string.c
@@ -27,7 +27,7 @@
 
 void * memset(void * dst, int val, size_t len)
 {
-    asm( "rep; stosb"
+    asm volatile ( "rep; stosb"
        : "=c" (len), "=D" (dst)
        : "0" (len), "1" (dst), "a" (val)
        : "memory" );
@@ -37,7 +37,7 @@ void * memset(void * dst, int val, size_t len)
 
 void * memcpy(void * dst, const void * src, size_t len)
 {
-    asm( "rep; movsb"
+    asm volatile ( "rep; movsb"
        : "=c" (len), "=D" (dst), "=S" (src)
        : "0" (len), "1" (dst), "2" (src)
        : "memory" );
diff --git a/i386/boot2/Makefile b/i386/boot2/Makefile
index 4aa84de..48d3c67 100644
--- a/i386/boot2/Makefile
+++ b/i386/boot2/Makefile
@@ -5,11 +5,11 @@
 DIR = boot2
 include ../MakePaths.dir
 
-OPTIM = -Os
+OPTIM = -Os -Oz
 CFLAGS	= $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
           -fno-builtin -DSAIO_INTERNAL_USER -static \
 	  -fomit-frame-pointer -mpreferred-stack-boundary=2 \
-	  -fno-align-functions
+	  -fno-align-functions -mno-sse2 -mfpmath=387
 DEFINES=
 CONFIG = hd
 SYMDIR = $(SYMROOT)
@@ -23,7 +23,7 @@ else
   MKDIRS = /bin/mkdir -p
 endif
 AS = as
-LD = ld
+LD = gcc
 # LIBS= -lc_static
 LIBS= -L$(SYMDIR) -lsaio -lsa
 LIBDEP= $(SYMDIR)/libsaio.a $(SYMDIR)/libsa.a
@@ -52,7 +52,8 @@ MAXBOOTSIZE = 65024
 all: $(DIRS_NEEDED) boot
 
 boot: machOconv $(OBJS) $(LIBDEP)
-	$(LD) -static -preload -segaddr __TEXT $(BOOT2ADDR) -segalign 20 \
+	$(LD) -static -Wl,-preload -Wl,-segaddr,__TEXT,$(BOOT2ADDR) \
+	        -nostdlib -arch i386 -Wl,-segalign,20 \
 		-o $(SYMROOT)/boot.sys $(filter %.o,$^) $(LIBS) -lcc_kext
 	machOconv $(SYMROOT)/boot.sys $(SYMROOT)/boot
 	size $(SYMROOT)/boot.sys
diff --git a/i386/boot2/WKdm.h b/i386/boot2/WKdm.h
new file mode 100644
index 0000000..be3ca2d
--- /dev/null
+++ b/i386/boot2/WKdm.h
@@ -0,0 +1,227 @@
+/* direct-mapped partial matching compressor with simple 22/10 split
+ *
+ *  Compresses buffers using a dictionary based match and partial match
+ *  (high bits only or full match) scheme.
+ *
+ *  Paul Wilson -- wilson@cs.utexas.edu
+ *  Scott F. Kaplan -- sfkaplan@cs.utexas.edu
+ *  September 1997
+ */
+
+/* compressed output format, in memory order
+ *  1. a four-word HEADER containing four one-word values:
+ *     i.   a one-word code saying what algorithm compressed the data
+ *     ii.  an integer WORD offset into the page saying
+ *          where the queue position area starts
+ *     iii. an integer WORD offset into the page saying where
+ *          the low-bits area starts
+ *     iv.  an integer WORD offset into the page saying where the
+ *          low-bits area ends
+ *
+ *  2. a 64-word TAGS AREA holding one two-bit tag for each word in 
+ *     the original (1024-word) page, packed 16 per word
+ *
+ *  3. a variable-sized FULL WORDS AREA (always word aligned and an
+ *     integral number of words) holding full-word patterns that
+ *     were not in the dictionary when encoded (i.e., dictionary misses)
+ *
+ *  4. a variable-sized QUEUE POSITIONS AREA (always word aligned and
+ *     an integral number of words) holding four-bit queue positions,
+ *     packed eight per word.
+ *
+ *  5. a variable-sized LOW BITS AREA (always word aligned and an
+ *     integral number of words) holding ten-bit low-bit patterns
+ *     (from partial matches), packed three per word. 
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ============================================================ */
+/* Included files */
+
+//#include <stdio.h>
+//#include <unistd.h>
+//#include <math.h>
+//#include <strings.h>
+
+typedef unsigned long WK_word;
+
+/* at the moment we have dependencies on the page size.  That should
+ * be changed to work for any power-of-two size that's at least 16
+ * words, or something like that
+ */
+
+#define PAGE_SIZE_IN_WORDS 1024
+#define PAGE_SIZE_IN_BYTES 4096
+
+#define DICTIONARY_SIZE 16
+
+/*
+ * macros defining the basic layout of stuff in a page
+ */
+#define HEADER_SIZE_IN_WORDS 4
+#define TAGS_AREA_OFFSET 4
+#define TAGS_AREA_SIZE 64
+
+/* the next few are used during compression to write the header */
+#define SET_QPOS_AREA_START(compr_dest_buf,qpos_start_addr)  \
+        (compr_dest_buf[1] = qpos_start_addr - compr_dest_buf)
+#define SET_LOW_BITS_AREA_START(compr_dest_buf,lb_start_addr) \
+        (compr_dest_buf[2] = lb_start_addr - compr_dest_buf)
+#define SET_LOW_BITS_AREA_END(compr_dest_buf,lb_end_addr) \
+        (compr_dest_buf[3] = lb_end_addr - compr_dest_buf)
+
+/* the next few are only use during decompression to read the header */
+#define TAGS_AREA_START(decomp_src_buf)       \
+        (decomp_src_buf + TAGS_AREA_OFFSET)
+#define TAGS_AREA_END(decomp_src_buf)         \
+        (TAGS_AREA_START(decomp_src_buf) + TAGS_AREA_SIZE)
+#define FULL_WORD_AREA_START(the_buf) TAGS_AREA_END(the_buf)
+#define QPOS_AREA_START(decomp_src_buf)       \
+        (decomp_src_buf + decomp_src_buf[1])   
+#define LOW_BITS_AREA_START(decomp_src_buf)   \
+        (decomp_src_buf + (decomp_src_buf[2]))
+#define QPOS_AREA_END(the_buf) LOW_BITS_AREA_START(the_buf)
+#define LOW_BITS_AREA_END(decomp_src_buf)     \
+        (decomp_src_buf + (decomp_src_buf[3]))
+
+/* ============================================================ */
+/* Types and structures */
+
+/* A structure to store each element of the dictionary. */
+typedef WK_word DictionaryElement;
+
+/* ============================================================ */
+/* Misc constants */
+
+#define BITS_PER_WORD 32
+#define BYTES_PER_WORD 4
+#define NUM_LOW_BITS 10
+#define LOW_BITS_MASK 0x3FF
+#define ALL_ONES_MASK 0xFFFFFFFF
+
+#define TWO_BITS_PACKING_MASK 0x03030303
+#define FOUR_BITS_PACKING_MASK 0x0F0F0F0F
+#define TEN_LOW_BITS_MASK 0x000003FF
+#define TWENTY_TWO_HIGH_BITS_MASK 0xFFFFFC00
+
+/* Tag values.  NOTE THAT CODE MAY DEPEND ON THE NUMBERS USED.
+ * Check for conditionals doing arithmetic on these things
+ * before changing them
+ */
+#define ZERO_TAG 0x0
+#define PARTIAL_TAG 0x1
+#define MISS_TAG 0x2
+#define EXACT_TAG 0x3
+
+#define BITS_PER_BYTE 8
+
+/* ============================================================ */
+/* Global macros */
+
+/* Shift out the low bits of a pattern to give the high bits pattern.
+   The stripped patterns are used for initial tests of partial
+   matches. */
+#define HIGH_BITS(word_pattern) (word_pattern >> NUM_LOW_BITS)
+
+/* String the high bits of a pattern so the low order bits can
+   be included in an encoding of a partial match. */
+#define LOW_BITS(word_pattern) (word_pattern & LOW_BITS_MASK)
+
+#if defined DEBUG_WK
+#define DEBUG_PRINT_1(string) printf (string)
+#define DEBUG_PRINT_2(string,value) printf(string, value)
+#else
+#define DEBUG_PRINT_1(string)
+#define DEBUG_PRINT_2(string, value)
+#endif
+
+/* Set up the dictionary before performing compression or
+   decompression.  Each element is loaded with some value, the
+   high-bits version of that value, and a next pointer. */
+#define PRELOAD_DICTIONARY { \
+  dictionary[0] = 1; \
+  dictionary[1] = 1; \
+  dictionary[2] = 1; \
+  dictionary[3] = 1; \
+  dictionary[4] = 1; \
+  dictionary[5] = 1; \
+  dictionary[6] = 1; \
+  dictionary[7] = 1; \
+  dictionary[8] = 1; \
+  dictionary[9] = 1; \
+  dictionary[10] = 1; \
+  dictionary[11] = 1; \
+  dictionary[12] = 1; \
+  dictionary[13] = 1; \
+  dictionary[14] = 1; \
+  dictionary[15] = 1; \
+}
+
+/* these are the constants for the hash function lookup table.
+ * Only zero maps to zero.  The rest of the tabale is the result
+ * of appending 17 randomizations of the multiples of 4 from
+ * 4 to 56.  Generated by a Scheme script in hash.scm. 
+ */
+#define HASH_LOOKUP_TABLE_CONTENTS { \
+   0, 52,  8, 56, 16, 12, 28, 20,  4, 36, 48, 24, 44, 40, 32, 60, \
+   8, 12, 28, 20,  4, 60, 16, 36, 24, 48, 44, 32, 52, 56, 40, 12, \
+   8, 48, 16, 52, 60, 28, 56, 32, 20, 24, 36, 40, 44,  4,  8, 40, \
+  60, 32, 20, 44,  4, 36, 52, 24, 16, 56, 48, 12, 28, 16,  8, 40, \
+  36, 28, 32, 12,  4, 44, 52, 20, 24, 48, 60, 56, 40, 48,  8, 32, \
+  28, 36,  4, 44, 20, 56, 60, 24, 52, 16, 12, 12,  4, 48, 20,  8, \
+  52, 16, 60, 24, 36, 44, 28, 56, 40, 32, 36, 20, 24, 60, 40, 44, \
+  52, 16, 32,  4, 48,  8, 28, 56, 12, 28, 32, 40, 52, 36, 16, 20, \
+  48,  8,  4, 60, 24, 56, 44, 12,  8, 36, 24, 28, 16, 60, 20, 56, \
+  32, 40, 48, 12,  4, 44, 52, 44, 40, 12, 56,  8, 36, 24, 60, 28, \
+  48,  4, 32, 20, 16, 52, 60, 12, 24, 36,  8,  4, 16, 56, 48, 44, \
+  40, 52, 32, 20, 28, 32, 12, 36, 28, 24, 56, 40, 16, 52, 44,  4, \
+  20, 60,  8, 48, 48, 52, 12, 20, 32, 44, 36, 28,  4, 40, 24,  8, \
+  56, 60, 16, 36, 32,  8, 40,  4, 52, 24, 44, 20, 12, 28, 48, 56, \
+  16, 60,  4, 52, 60, 48, 20, 16, 56, 44, 24,  8, 40, 12, 32, 28, \
+  36, 24, 32, 12,  4, 20, 16, 60, 36, 28,  8, 52, 40, 48, 44, 56  \
+}
+
+#define HASH_TO_DICT_BYTE_OFFSET(pattern) \
+        (hashLookupTable[((pattern) >> 10) & 0xFF])
+
+extern const char hashLookupTable[];
+
+/* EMIT... macros emit bytes or words into the intermediate arrays
+ */
+
+#define EMIT_BYTE(fill_ptr, byte_value) {*fill_ptr = byte_value; fill_ptr++;}
+#define EMIT_WORD(fill_ptr,word_value) {*fill_ptr = word_value; fill_ptr++;}
+
+/* RECORD... macros record the results of modeling in the intermediate
+ * arrays
+ */
+
+#define RECORD_ZERO { EMIT_BYTE(next_tag,ZERO_TAG); }
+
+#define RECORD_EXACT(queue_posn)  EMIT_BYTE(next_tag,EXACT_TAG);  \
+                                  EMIT_BYTE(next_qp,(queue_posn)); 
+
+#define RECORD_PARTIAL(queue_posn,low_bits_pattern) { \
+   EMIT_BYTE(next_tag,PARTIAL_TAG);                   \
+   EMIT_BYTE(next_qp,(queue_posn));                   \
+   EMIT_WORD(next_low_bits,(low_bits_pattern))  }
+
+#define RECORD_MISS(word_pattern) EMIT_BYTE(next_tag,MISS_TAG); \
+                                  EMIT_WORD(next_full_patt,(word_pattern)); 
+				  
+void
+WKdm_decompress (WK_word* src_buf,
+		 WK_word* dest_buf,
+		 unsigned int words);
+unsigned int
+WKdm_compress (WK_word* src_buf,
+               WK_word* dest_buf,
+	       unsigned int num_input_words);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/i386/boot2/WKdmDecompress.c b/i386/boot2/WKdmDecompress.c
new file mode 100644
index 0000000..fd230ca
--- /dev/null
+++ b/i386/boot2/WKdmDecompress.c
@@ -0,0 +1,285 @@
+#include <sys/cdefs.h>
+#include "WKdm.h"
+
+/* Part of __HIB section */
+
+/***************************************************************************
+ *          THE UNPACKING ROUTINES should GO HERE
+ */
+
+const char hashLookupTable [] = HASH_LOOKUP_TABLE_CONTENTS;
+
+#if 0
+#define GET_NEXT_TAG tags[tagsIndex++]
+#define GET_NEXT_FULL_PATTERN fullPatterns[fullPatternsIndex++]
+#define GET_NEXT_LOW_BITS lowBits[lowBitsIndex++]
+#define GET_NEXT_DICTIONARY_INDEX dictionaryIndices[dictionaryIndicesIndex++]
+#endif
+
+/*  WK_unpack_2bits takes any number of words containing 16 two-bit values
+ *  and unpacks them into four times as many words containg those
+ *  two bit values as bytes (with the low two bits of each byte holding
+ *  the actual value.
+ */
+static WK_word*
+WK_unpack_2bits(WK_word *input_buf,
+                WK_word *input_end,
+                WK_word *output_buf) {
+
+  register WK_word *input_next = input_buf;
+  register WK_word *output_next = output_buf;
+  register WK_word packing_mask = TWO_BITS_PACKING_MASK;
+
+  /* loop to repeatedly grab one input word and unpack it into
+   * 4 output words.  This loop could be unrolled a little---it's
+   * designed to be easy to do that.
+   */   
+  while (input_next < input_end) {
+    register WK_word temp = input_next[0];
+    DEBUG_PRINT_2("Unpacked tags word: %.8x\n", temp);
+    output_next[0] = temp & packing_mask;
+    output_next[1] = (temp >> 2) & packing_mask;
+    output_next[2] = (temp >> 4) & packing_mask;
+    output_next[3] = (temp >> 6) & packing_mask;
+    
+    output_next += 4;
+    input_next++;
+  }
+
+  return output_next;
+
+}
+
+/* unpack four bits consumes any number of words (between input_buf
+ * and input_end) holding 8 4-bit values per word, and unpacks them
+ * into twice as many words, with each value in a separate byte.
+ * (The four-bit values occupy the low halves of the bytes in the
+ * result).
+ */
+static WK_word*
+WK_unpack_4bits(WK_word *input_buf,
+                WK_word *input_end,
+                WK_word *output_buf) {
+
+  register WK_word *input_next = input_buf;
+  register WK_word *output_next = output_buf;
+  register WK_word packing_mask = FOUR_BITS_PACKING_MASK;
+  
+  
+  /* loop to repeatedly grab one input word and unpack it into
+   * 4 output words.  This loop should probably be unrolled
+   * a little---it's designed to be easy to do that.
+   */   
+  while (input_next < input_end) {
+    register WK_word temp = input_next[0];
+    DEBUG_PRINT_2("Unpacked dictionary indices word: %.8x\n", temp);
+    output_next[0] = temp & packing_mask;
+    output_next[1] = (temp >> 4) & packing_mask;
+    
+    output_next += 2;
+    input_next++;
+  }
+  
+  return output_next;
+
+}
+
+/* unpack_3_tenbits unpacks three 10-bit items from (the low 30 bits of)
+ * a 32-bit word
+ */
+static WK_word*
+WK_unpack_3_tenbits(WK_word *input_buf,
+                    WK_word *input_end,
+                    WK_word *output_buf) {
+
+  register WK_word *input_next = input_buf;
+  register WK_word *output_next = output_buf;
+  register WK_word packing_mask = LOW_BITS_MASK;
+  
+  /* loop to fetch words of input, splitting each into three
+   * words of output with 10 meaningful low bits.  This loop
+   * probably ought to be unrolled and maybe coiled
+   */
+  while (input_next < input_end) {
+    register WK_word temp = input_next[0];
+    
+    output_next[0] = temp & packing_mask;
+    output_next[1] = (temp >> 10) & packing_mask;
+    output_next[2] = temp >> 20;
+    
+    input_next++;
+    output_next += 3;
+  }
+  
+  return output_next;
+
+}
+
+/*********************************************************************
+ * WKdm_decompress --- THE DECOMPRESSOR                                 
+ * Expects WORD pointers to the source and destination buffers
+ * and a page size in words.  The page size had better be 1024 unless     
+ * somebody finds the places that are dependent on the page size and 
+ * fixes them
+ */
+
+void
+WKdm_decompress (WK_word* src_buf,
+		 WK_word* dest_buf,
+		 __unused unsigned int words)
+{
+
+  DictionaryElement dictionary[DICTIONARY_SIZE];
+
+  /* arrays that hold output data in intermediate form during modeling */
+  /* and whose contents are packed into the actual output after modeling */
+
+  /* sizes of these arrays should be increased if you want to compress
+   * pages larger than 4KB
+   */
+  WK_word tempTagsArray[300];        /* tags for everything          */
+  WK_word tempQPosArray[300];        /* queue positions for matches  */
+  WK_word tempLowBitsArray[1200];    /* low bits for partial matches */
+
+  PRELOAD_DICTIONARY;
+
+#ifdef WK_DEBUG
+  printf("\nIn DECOMPRESSOR\n");
+  printf("tempTagsArray is at %u\n", (unsigned long int) tempTagsArray);
+  printf("tempQPosArray is at %u\n", (unsigned long int) tempQPosArray);
+  printf("tempLowBitsArray is at %u\n", (unsigned long int) tempLowBitsArray);
+
+  printf(" first four words of source buffer are:\n");
+  printf("   %u\n   %u\n   %u\n   %u\n",
+         src_buf[0], src_buf[1], src_buf[2], src_buf[3]);
+  
+  { int i;
+    WK_word *arr =(src_buf + TAGS_AREA_OFFSET + (PAGE_SIZE_IN_WORDS / 16));
+
+    printf("  first 20 full patterns are: \n");
+    for (i = 0; i < 20; i++) {
+      printf(" %d", arr[i]);
+    }
+    printf("\n");
+  }
+#endif
+
+  WK_unpack_2bits(TAGS_AREA_START(src_buf),
+                  TAGS_AREA_END(src_buf),
+                  tempTagsArray);
+
+#ifdef WK_DEBUG
+  { int i;
+    char* arr = (char *) tempTagsArray;
+
+    printf("  first 200 tags are: \n");
+    for (i = 0; i < 200; i++) {
+      printf(" %d", arr[i]);
+    }
+    printf("\n");
+  }
+#endif
+
+  WK_unpack_4bits(QPOS_AREA_START(src_buf),
+                  QPOS_AREA_END(src_buf),
+                  tempQPosArray);
+
+#ifdef WK_DEBUG
+  { int i;
+    char* arr = (char *) tempQPosArray;
+
+    printf("  first 200 queue positions are: \n");
+    for (i = 0; i < 200; i++) {
+      printf(" %d", arr[i]);
+    }
+    printf("\n");
+  }
+#endif
+
+  WK_unpack_3_tenbits(LOW_BITS_AREA_START(src_buf),
+                      LOW_BITS_AREA_END(src_buf),
+                      tempLowBitsArray);
+
+#ifdef WK_DEBUG
+  printf("AFTER UNPACKING, about to enter main block \n");
+#endif
+
+  {
+    register char *next_tag = (char *) tempTagsArray;
+    char *tags_area_end =
+       ((char *) tempTagsArray) + PAGE_SIZE_IN_WORDS;
+    char *next_q_pos = (char *) tempQPosArray;
+    WK_word *next_low_bits = tempLowBitsArray;
+    WK_word *next_full_word = FULL_WORD_AREA_START(src_buf);
+
+    WK_word *next_output = dest_buf;
+
+#ifdef WK_DEBUG
+    printf("next_output is %u\n", next_output);
+
+    printf("next_tag is %u \n", next_tag);
+    printf("tags_area_end is %u\n", tags_area_end);
+    printf("next_q_pos is %u\n", next_q_pos);
+    printf("next_low_bits is %u\n", next_low_bits);
+    printf("next_full_word is %u\n", next_full_word);
+#endif 
+
+    /* this loop should probably be unrolled. Maybe we should unpack
+     * as 4 bit values, giving two consecutive tags, and switch on
+     * that 16 ways to decompress 2 words at a whack
+     */
+    while (next_tag < tags_area_end) {
+
+       char tag = next_tag[0];
+
+       switch(tag) {
+
+         case ZERO_TAG: {
+            *next_output = 0;
+            break;
+         }
+         case EXACT_TAG: {
+            WK_word *dict_location = dictionary + *(next_q_pos++);
+            /* no need to replace dict. entry if matched exactly */
+            *next_output = *dict_location;
+            break;
+         }
+         case PARTIAL_TAG: {
+            WK_word *dict_location = dictionary + *(next_q_pos++);
+            {
+               WK_word temp = *dict_location;
+
+               /* strip out low bits */
+               temp = ((temp >> NUM_LOW_BITS) << NUM_LOW_BITS);
+
+               /* add in stored low bits from temp array */
+               temp = temp | *(next_low_bits++);
+
+               *dict_location = temp;      /* replace old value in dict. */
+               *next_output = temp;    /* and echo it to output */
+            }
+            break;
+         }
+         case MISS_TAG: {
+            WK_word missed_word = *(next_full_word++);
+            WK_word *dict_location = 
+              (WK_word *)
+              (((char *) dictionary) + HASH_TO_DICT_BYTE_OFFSET(missed_word));
+            *dict_location = missed_word;
+            *next_output = missed_word;
+            break;
+         }
+       }
+       next_tag++;
+       next_output++;
+    }
+
+#ifdef WK_DEBUG        
+    printf("AFTER DECOMPRESSING\n");
+    printf("next_output is %u\n", (unsigned long int) next_output);
+    printf("next_tag is %u\n", (unsigned long int) next_tag);
+    printf("next_full_word is %u\n", (unsigned long int) next_full_word);
+    printf("next_q_pos is %u\n", (unsigned long int) next_q_pos);
+#endif
+  }
+}
diff --git a/i386/boot2/boot.c b/i386/boot2/boot.c
index 9bd0829..d935082 100644
--- a/i386/boot2/boot.c
+++ b/i386/boot2/boot.c
@@ -61,6 +61,7 @@ BOOL gOverrideKernel;
 static char gBootKernelCacheFile[512];
 static char gCacheNameAdler[64 + 256];
 char *gPlatformName = gCacheNameAdler;
+char gRootDevice[512];
 char gMKextName[512];
 BVRef gBootVolume;
 
@@ -103,7 +104,7 @@ static void malloc_error(char *addr, size_t size)
 {
     printf("\nMemory allocation error (0x%x, 0x%x)\n",
            (unsigned)addr, (unsigned)size);
-    asm("hlt");
+    asm volatile ("hlt");
 }
 
 //==========================================================================
@@ -113,9 +114,6 @@ static int ExecKernel(void *binary)
 {
     entry_t                   kernelEntry;
     int                       ret;
-#ifdef APM_SUPPORT
-    BOOL                      apm;
-#endif /* APM_SUPPORT */
     BOOL                      bootGraphics;
 
     bootArgs->kaddr = bootArgs->ksize = 0;
@@ -123,7 +121,7 @@ static int ExecKernel(void *binary)
     ret = DecodeKernel(binary,
                        &kernelEntry,
                        (char **) &bootArgs->kaddr,
-                       &bootArgs->ksize );
+                       (int *)&bootArgs->ksize );
 
     if ( ret != 0 )
         return ret;
@@ -147,17 +145,6 @@ static int ExecKernel(void *binary)
 
     printf("Starting Darwin/x86");
 
-    turnOffFloppy();
-
-#ifdef APM_SUPPORT
-    // Connect to APM BIOS.
-
-    if ( getBoolForKey("APM", &apm) && apm == YES )
-    {
-        if ( APMPresent() ) APMConnect32();
-    }
-#endif /* APM_SUPPORT */
-
     // Cleanup the PXE base code.
 
     if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) {
@@ -176,20 +163,24 @@ static int ExecKernel(void *binary)
     }
 
     if (bootGraphics) {
-        if (bootArgs->graphicsMode == TEXT_MODE) {
+        if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
             // If we were in text mode, switch to graphics mode.
-            // This will draw the boot graphics.
+            // 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 {
-        if (bootArgs->graphicsMode == GRAPHICS_MODE) {
-            setVideoMode( TEXT_MODE );
-        }
+        // 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, bootArgs );
@@ -207,13 +198,13 @@ static void scanHardware()
     extern int  ReadPCIBusInfo(PCI_bus_info_t *);
     extern void PCI_Bus_Init(PCI_bus_info_t *);
 
-    ReadPCIBusInfo( &bootArgs->pciInfo );
+    ReadPCIBusInfo( &bootInfo->pciInfo );
     
     //
     // Initialize PCI matching support in the booter.
     // Not used, commented out to minimize code size.
     //
-    // PCI_Bus_Init( &bootArgs->pciInfo );
+    // PCI_Bus_Init( &bootInfo->pciInfo );
 }
 
 //==========================================================================
@@ -242,7 +233,6 @@ void boot(int biosdev)
     zeroBSS();
 
     // Initialize malloc
-
     malloc_init(0, 0, 0, malloc_error);
 
     // Enable A20 gate before accessing memory above 1Mb.
@@ -266,10 +256,21 @@ void boot(int biosdev)
     // Not sure if it is safe to call setVideoMode() before the
     // config table has been loaded. Call video_mode() instead.
 
+#if DEBUG
+    printf("before video_mode\n");
+#endif
     video_mode( 2 );  // 80x25 mono text mode.
+#if DEBUG
+    printf("after video_mode\n");
+#endif
 
-    // Scan hardware configuration.
+    // 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();
 
     // First get info for boot volume.
@@ -277,7 +278,7 @@ void boot(int biosdev)
 
     // Record default boot device.
     gBootVolume = selectBootVolume(bvChain);
-    bootArgs->kernDev = MAKEKERNDEV(gBIOSDev,
+    bootInfo->kernDev = MAKEKERNDEV(gBIOSDev,
                                     BIOS_DEV_UNIT(gBootVolume),
                                     gBootVolume->part_no );
 
@@ -297,6 +298,7 @@ void boot(int biosdev)
         int trycache;
         long flags, cachetime, kerneltime, exttime;
         int ret = -1;
+        void *binary = (void *)kLoadAddr;
 
         // Initialize globals.
 
@@ -315,19 +317,11 @@ void boot(int biosdev)
 
 
         // Reset cache name.
-        bzero(gCacheNameAdler, sizeof(gCacheNameAdler));
+        bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
 
-        if ( getValueForKey( kRootDeviceKey, &val, &len ) == YES ) {
-            if (*val == '*') {
-                val++;
-                len--;
-            }
-            strncpy( gCacheNameAdler + 64, val, len );
-            sprintf(gCacheNameAdler + 64 + len, ",%s", bootArgs->bootFile);
-        } else {
-            strcpy(gCacheNameAdler + 64, bootArgs->bootFile);
-        }
-        adler32 = Adler32(gCacheNameAdler, sizeof(gCacheNameAdler));
+        sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile);
+
+        adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
 
         if (getValueForKey(kKernelCacheKey, &val, &len) == YES) {
             strlcpy(gBootKernelCacheFile, val, len+1);
@@ -337,7 +331,6 @@ void boot(int biosdev)
 
         // Check for cache file.
 
-
         trycache = (((gBootMode & kBootModeSafe) == 0) &&
                     (gOverrideKernel == NO) &&
                     (gBootFileType == kBlockDeviceType) &&
@@ -349,7 +342,7 @@ void boot(int biosdev)
         if (trycache) do {
       
             // if we haven't found the kernel yet, don't use the cache
-            ret = GetFileInfo(NULL, bootArgs->bootFile, &flags, &kerneltime);
+            ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
             if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
                 trycache = 0;
                 break;
@@ -380,13 +373,14 @@ void boot(int biosdev)
                 bootFile = gBootKernelCacheFile;
                 verbose("Loading kernel cache %s\n", bootFile);
                 ret = LoadFile(bootFile);
+                binary = (void *)kLoadAddr;
                 if (ret >= 0) {
                     break;
                 }
             }
-            bootFile = bootArgs->bootFile;
+            bootFile = bootInfo->bootFile;
             verbose("Loading kernel %s\n", bootFile);
-            ret = LoadFile(bootFile);
+            ret = LoadThinFatFile(bootFile, &binary);
         } while (0);
 
         clearActivityIndicator();
@@ -398,14 +392,7 @@ void boot(int biosdev)
         if (ret < 0) {
             error("Can't find %s\n", bootFile);
 
-            if ( gBootFileType == kBIOSDevTypeFloppy )
-            {
-                // floppy in drive, but failed to load kernel.
-                gBIOSDev = kBIOSDevTypeHardDrive;
-                initKernBootStruct( gBIOSDev );
-                printf("Attempting to load from hard drive...");
-            }
-            else if ( gBootFileType == kNetworkDeviceType )
+            if ( gBootFileType == kNetworkDeviceType )
             {
                 // Return control back to PXE. Don't unload PXE base code.
                 gUnloadPXEOnExit = 0;
@@ -413,7 +400,7 @@ void boot(int biosdev)
             }
         } else {
             /* Won't return if successful. */
-            ret = ExecKernel((void *)kLoadAddr);
+            ret = ExecKernel(binary);
         }
 
     } /* while(1) */
@@ -459,3 +446,4 @@ unsigned long Adler32(unsigned char *buf, long len)
     return OSSwapHostToBigInt32(result);
 }
 
+
diff --git a/i386/boot2/boot.h b/i386/boot2/boot.h
index dc7d3ab..98982f4 100644
--- a/i386/boot2/boot.h
+++ b/i386/boot2/boot.h
@@ -45,8 +45,12 @@
 #define kBootDeviceKey      "Boot Device"
 #define kTimeoutKey         "Timeout"
 #define kRootDeviceKey      "rd"
+#define kBootUUIDKey        "boot-uuid"
 #define kPlatformKey        "platform"
 #define kACPIKey            "acpi"
+#define kCDROMPromptKey     "CD-ROM Prompt"
+#define kCDROMOptionKey     "CD-ROM Option Key"
+
 #define kDefaultKernel      "mach_kernel"
 
 /*
@@ -54,14 +58,16 @@
  *
  */
 #define kVerboseModeFlag     "-v"
-#define kSafeModeFlag        "-f"
+#define kSafeModeFlag        "-x"
+#define kOldSafeModeFlag     "-f"
 #define kIgnoreBootFileFlag  "-F"
 #define kSingleUserModeFlag  "-s"
 
 /*
  * Booter behavior control
  */
-#define kBootTimeout         8
+#define kBootTimeout         -1
+#define kCDBootTimeout       8
 
 /*
  * A global set by boot() to record the device that the booter
@@ -75,6 +81,7 @@ extern char bootPrompt[];
 extern BOOL gOverrideKernel;
 extern char *gPlatformName;
 extern char gMKextName[];
+extern char gRootDevice[];
 extern BVRef gBootVolume;
 
 // Boot Modes
@@ -111,6 +118,7 @@ convertImage( unsigned short width,
               unsigned char **newImageData );
 extern char * decodeRLE( const void * rleData, int rleBlocks, int outBytes );
 extern void drawBootGraphics(void);
+extern int getVideoMode(void);
 
 /*
  * drivers.c
diff --git a/i386/boot2/drivers.c b/i386/boot2/drivers.c
index ab7742a..aec4574 100644
--- a/i386/boot2/drivers.c
+++ b/i386/boot2/drivers.c
@@ -159,7 +159,10 @@ long LoadDrivers( char * dirSpec )
 
     if ( gBootFileType == kNetworkDeviceType )
     {
-        NetLoadDrivers(dirSpec);
+        if (NetLoadDrivers(dirSpec) != 0) {
+            error("Could not load drivers from the network\n");
+            return -1;
+        }
     }
     else if ( gBootFileType == kBlockDeviceType )
     {
@@ -284,7 +287,7 @@ NetLoadDrivers( char * dirSpec )
 #endif
 
     // INTEL modification
-    sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootArgs->bootFile);
+    sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootInfo->bootFile);
     
     verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
     
@@ -307,22 +310,20 @@ LoadDriverMKext( char * fileSpec )
     unsigned long    driversAddr, driversLength;
     long             length;
     char             segName[32];
-    DriversPackage * package = (DriversPackage *)kLoadAddr;
+    DriversPackage * package;
 
 #define GetPackageElement(e)     OSSwapBigToHostInt32(package->e)
 
     // Load the MKext.
-    length = LoadFile(fileSpec);
+    length = LoadThinFatFile(fileSpec, (void **)&package);
     if (length == -1) return -1;
 
-    ThinFatFile((void **)&package, &length);
-
     // Verify the MKext.
     if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
         ( GetPackageElement(signature2) != kDriverPackageSignature2) ||
         ( GetPackageElement(length)      > kLoadSize )               ||
         ( GetPackageElement(alder32)    !=
-          Alder32((char *)&package->version, GetPackageElement(length) - 0x10) ) )
+          Alder32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
     {
         return -1;
     }
@@ -435,53 +436,6 @@ LoadDriverPList( char * dirSpec, char * name, long bundleType )
     return ret;
 }
 
-#if 0
-//==========================================================================
-// ThinFatFile
-// Checks the loaded file for a fat header; if present, updates
-// loadAddr and length to be the portion of the fat file relevant
-// to the current architecture; otherwise leaves them unchanged.
-
-static void
-ThinFatFile(void **loadAddrP, unsigned long *lengthP)
-{
-    // Check for fat files.
-    struct fat_header *fhp = (struct fat_header *)kLoadAddr;
-    struct fat_arch *fap = (struct fat_arch *)((void *)kLoadAddr +
-					       sizeof(struct fat_header));
-    int nfat, swapped;
-    void *loadAddr = 0;
-    unsigned long length = 0;
-
-    if (fhp->magic == FAT_MAGIC) {
-	nfat = fhp->nfat_arch;
-	swapped = 0;
-    } else if (fhp->magic == FAT_CIGAM) {
-	nfat = OSSwapInt32(fhp->nfat_arch);
-	swapped = 1;
-    } else {
-	nfat = 0;
-	swapped = 0;
-    }
-
-    for (; nfat > 0; nfat--, fap++) {
-	if (swapped) {
-	    fap->cputype = OSSwapInt32(fap->cputype);
-	    fap->offset = OSSwapInt32(fap->offset);
-	    fap->size = OSSwapInt32(fap->size);
-	}
-	if (fap->cputype == CPU_TYPE_I386) {
-	    loadAddr = (void *)kLoadAddr + fap->offset;
-	    length = fap->size;
-	    break;
-	}
-    }
-    if (loadAddr)
-	*loadAddrP = loadAddr;
-    if (length)
-	*lengthP = length;
-}
-#endif
 
 //==========================================================================
 // LoadMatchedModules
@@ -494,6 +448,8 @@ LoadMatchedModules( void )
     char          *fileName, segName[32];
     DriverInfoPtr driver;
     long          length, driverAddr, driverLength;
+    void          *driverModuleAddr = 0;
+
   
     module = gModuleHead;
 
@@ -507,18 +463,21 @@ LoadMatchedModules( void )
             {
                 fileName = prop->string;
                 sprintf(gFileSpec, "%s%s", module->driverPath, fileName);
-                length = LoadFile(gFileSpec);
+                length = LoadThinFatFile(gFileSpec, &driverModuleAddr);
+                //length = LoadFile(gFileSpec);
+                //driverModuleAddr = (void *)kLoadAddr;
+                //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc();
             }
             else
                 length = 0;
 
             if (length != -1)
             {
-		void *driverModuleAddr = (void *)kLoadAddr;
-                if (length != 0)
-                {
-		    ThinFatFile(&driverModuleAddr, &length);
-		}
+		//driverModuleAddr = (void *)kLoadAddr;
+                //if (length != 0)
+                //{
+		//    ThinFatFile(&driverModuleAddr, &length);
+		//}
 
                 // Make make in the image area.
                 driverLength = sizeof(DriverInfo) + module->plistLength + length;
diff --git a/i386/boot2/graphics.c b/i386/boot2/graphics.c
index 89c6268..466f0ad 100644
--- a/i386/boot2/graphics.c
+++ b/i386/boot2/graphics.c
@@ -52,6 +52,7 @@ void drawDataRectangle( unsigned short  x,
                                unsigned short  height,
                         unsigned char * data );
 
+static void setBorderColor( unsigned char colorIndex );
 
 int
 convertImage( unsigned short width,
@@ -59,7 +60,7 @@ convertImage( unsigned short width,
               const unsigned char *imageData,
               unsigned char **newImageData );
 
-#define VIDEO(x) (bootArgs->video.v_ ## x)
+#define VIDEO(x) (bootArgs->Video.v_ ## x)
 
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 
@@ -81,7 +82,7 @@ void printVBEInfo()
 
     // Check presence of VESA signature.
 
-    if ( strncmp( vbeInfo.VESASignature, "VESA", 4 ) )
+    if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
         return;
 
     // Announce controller properties.
@@ -428,12 +429,12 @@ setVESAGraphicsMode( unsigned short width,
         // Update KernBootStruct using info provided by the selected
         // VESA mode.
 
-        bootArgs->graphicsMode     = GRAPHICS_MODE;
-        bootArgs->video.v_width    = minfo.XResolution;
-        bootArgs->video.v_height   = minfo.YResolution;
-        bootArgs->video.v_depth    = minfo.BitsPerPixel;
-        bootArgs->video.v_rowBytes = minfo.BytesPerScanline;
-        bootArgs->video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
+        bootArgs->Video.v_display  = GRAPHICS_MODE;
+        bootArgs->Video.v_width    = minfo.XResolution;
+        bootArgs->Video.v_height   = minfo.YResolution;
+        bootArgs->Video.v_depth    = minfo.BitsPerPixel;
+        bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
+        bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
 
     }
     while ( 0 );
@@ -494,6 +495,8 @@ drawBootGraphics( void )
         drawColorRectangle( 0, 0, VIDEO(width), VIDEO(height),
                             0x01 /* color index */ );
 
+        setBorderColor( 0x01 /* color index */ );
+
         appleBootPict = decodeRLE( gAppleBootPictRLE, kAppleBootRLEBlocks,
                                    kAppleBootWidth * kAppleBootHeight );
 
@@ -502,7 +505,7 @@ drawBootGraphics( void )
         if ( appleBootPict )
         {
             convertImage(kAppleBootWidth, kAppleBootHeight,
-                         appleBootPict, &imageData);
+                         (unsigned char *)appleBootPict, &imageData);
 
             x = ( VIDEO(width) - kAppleBootWidth ) / 2;
             y = ( VIDEO(height) - kAppleBootHeight ) / 2 + kAppleBootOffset;
@@ -559,7 +562,7 @@ static unsigned long lookUpCLUTIndex( unsigned char index,
 
 static void * stosl(void * dst, long val, long len)
 {
-    asm( "rep; stosl"
+    asm volatile ( "rep; stosl"
        : "=c" (len), "=D" (dst)
        : "0" (len), "1" (dst), "a" (val)
        : "memory" );
@@ -616,6 +619,29 @@ void drawDataRectangle( unsigned short  x,
     }
 }
 
+
+//==========================================================================
+// setBorderColor
+
+static void
+setBorderColor( unsigned char  colorIndex )
+{
+    long   color = lookUpCLUTIndex( colorIndex, 32 );
+    VBEInfoBlock     vbeInfo;
+    int              err;
+
+    // Get VBE controller info.
+
+    bzero( &vbeInfo, sizeof(vbeInfo) );
+    err = getVBEInfo( &vbeInfo );
+    if ( err != errSuccess )
+    {
+        return;
+    }
+
+}
+
+
 //==========================================================================
 // setVESATextMode
 
@@ -646,12 +672,12 @@ setVESATextMode( unsigned short cols,
     // Update KernBootStruct using info provided by the selected
     // VESA mode.
 
-    bootArgs->graphicsMode     = TEXT_MODE;
-    bootArgs->video.v_baseAddr = 0xb8000;
-    bootArgs->video.v_width    = minfo.XResolution;
-    bootArgs->video.v_height   = minfo.YResolution;
-    bootArgs->video.v_depth    = 8;
-    bootArgs->video.v_rowBytes = 0x8000;
+    bootArgs->Video.v_display  = VGA_TEXT_MODE;
+    bootArgs->Video.v_baseAddr = 0xb8000;
+    bootArgs->Video.v_width    = minfo.XResolution;
+    bootArgs->Video.v_height   = minfo.YResolution;
+    bootArgs->Video.v_depth    = 8;
+    bootArgs->Video.v_rowBytes = 0x8000;
 
     return errSuccess;  // always return success
 }
@@ -696,7 +722,7 @@ getNumberArrayFromProperty( const char *  propKey,
 //==========================================================================
 // setVideoMode
 //
-// Set the video mode to TEXT_MODE or GRAPHICS_MODE.
+// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
 
 void
 setVideoMode( int mode )
@@ -725,19 +751,17 @@ setVideoMode( int mode )
         err = setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
         if ( err == errSuccess )
         {
-            // If this boolean is set to true, then the console driver
-            // in the kernel will show the animated color wheel on the
-            // upper left corner.
-
-            bootArgs->video.v_display = !gVerboseMode;
-            
-            if (!gVerboseMode) {
+            if (gVerboseMode) {
+                // Tell the kernel to use text mode on a linear frame buffer display
+                bootArgs->Video.v_display = FB_TEXT_MODE;
+            } else {
+                bootArgs->Video.v_display = GRAPHICS_MODE;
                 drawBootGraphics();
             }
         }
     }
 
-    if ( (mode == TEXT_MODE) || (err != errSuccess) )
+    if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
     {
         count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
         if ( count < 2 )
@@ -747,18 +771,18 @@ setVideoMode( int mode )
         }
 
         setVESATextMode( params[0], params[1], 4 );
-        bootArgs->video.v_display = 0;
+        bootArgs->Video.v_display = VGA_TEXT_MODE;
     }
 
     currentIndicator = 0;
 }
 
 //==========================================================================
-// Return the current video mode, TEXT_MODE or GRAPHICS_MODE.
+// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
 
 int getVideoMode(void)
 {
-    return bootArgs->graphicsMode;
+    return bootArgs->Video.v_display;
 }
 
 //==========================================================================
@@ -783,7 +807,7 @@ spinActivityIndicator( void )
     else
         lastTickTime = currentTickTime;
 
-    if ( getVideoMode() == TEXT_MODE )
+    if ( getVideoMode() == VGA_TEXT_MODE )
     {
         if (currentIndicator >= kNumIndicators) currentIndicator = 0;
         string[0] = indicator[currentIndicator++];
@@ -794,7 +818,7 @@ spinActivityIndicator( void )
 void
 clearActivityIndicator( void )
 {
-    if ( getVideoMode() == TEXT_MODE )
+    if ( getVideoMode() == VGA_TEXT_MODE )
     {
         printf(" \b");
     }
diff --git a/i386/boot2/options.c b/i386/boot2/options.c
index 02000fb..4427aae 100644
--- a/i386/boot2/options.c
+++ b/i386/boot2/options.c
@@ -43,11 +43,6 @@ static void showHelp();
 
 //==========================================================================
 
-enum {
-    kCursorTypeHidden    = 0x0100,
-    kCursorTypeUnderline = 0x0607
-};
-
 typedef struct {
     int x;
     int y;
@@ -101,7 +96,7 @@ static int countdown( const char * msg, int row, int timeout )
     moveCursor( 0, row );
     printf(msg);
 
-    for ( time = time18(), timeout++; timeout; )
+    for ( time = time18(), timeout++; timeout > 0; )
     {
         if (ch = readKeyboardStatus())
             break;
@@ -395,7 +390,7 @@ printMemoryInfo(void)
 {
     int line;
     int i;
-    MemoryRange *mp = bootArgs->memoryMap;
+    MemoryRange *mp = bootInfo->memoryMap;
 
     // Activate and clear page 1
     setActiveDisplayPage(1);
@@ -404,7 +399,7 @@ printMemoryInfo(void)
 
     printf("BIOS reported memory ranges:\n");
     line = 1;
-    for (i=0; i<bootArgs->memoryMapCount; i++) {
+    for (i=0; i<bootInfo->memoryMapCount; i++) {
         printf("Base 0x%08x%08x, ",
                (unsigned long)(mp->base >> 32),
                (unsigned long)(mp->base));
@@ -441,20 +436,29 @@ getBootOptions(BOOL firstRun)
     BVRef   bvr;
     BVRef   bvChain;
     BVRef   menuBVR;
-    BOOL    showPrompt, newShowPrompt;
+    BOOL    showPrompt, newShowPrompt, isCDROM;
     MenuItem *  menuItems = NULL;
 
+    if ( diskIsCDROM(gBootVolume) )
+        isCDROM = TRUE;
+    else
+        isCDROM = FALSE;
+
     // Allow user to override default timeout.
 
     if ( getIntForKey(kTimeoutKey, &timeout) == NO )
     {
-        timeout = kBootTimeout;
+        if ( isCDROM )
+            timeout = kCDBootTimeout;
+        else
+            timeout = kBootTimeout;
     }
+    if (timeout < 0) gBootMode |= kBootModeQuiet;
 
-    // If the user is holding down a shift key,
-    // abort quiet mode.
+    // If the user is holding down a modifier key,
+    // enter safe mode.
     if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) {
-        gBootMode &= ~kBootModeQuiet;
+        gBootMode |= kBootModeSafe;
     }
 
     // If user typed F8, abort quiet mode,
@@ -470,7 +474,7 @@ getBootOptions(BOOL firstRun)
     clearScreenRows( 0, kScreenLastRow );
     if ( ! ( gBootMode & kBootModeQuiet ) ) {
         // Display banner and show hardware info. 
-        printf( bootBanner, (bootArgs->convmem + bootArgs->extmem) / 1024 );
+        printf( bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024 );
         printVBEInfo();
     }
 
@@ -483,32 +487,61 @@ getBootOptions(BOOL firstRun)
     bvChain = scanBootVolumes( gBIOSDev, &bvCount );
     gBootVolume = menuBVR = selectBootVolume( bvChain );
 
-#if 0
-    // When booting from CD (via HD emulation), default to hard
+    // When booting from CD, default to hard
     // drive boot when possible. 
 
-    if ( gBootVolume->part_type == FDISK_BOOTER &&
-         gBootVolume->biosdev   == 0x80 )
+    if ( isCDROM )
     {
-        // Scan the original device 0x80 that has been displaced
-        // by the CD-ROM.
+        const char *val;
+        char *prompt;
+        int cnt;
+        int optionKey;
+
+        if (getValueForKey( kCDROMPromptKey, &val, &cnt )) {
+            cnt += 1;
+            prompt = malloc(cnt);
+            strlcpy(prompt, val, cnt);
+        } else {
+            prompt = "Press any key to start up from CD-ROM, "
+                "or press F8 to enter startup options.";
+            cnt = 0;
+        }
 
-        BVRef hd_bvr = selectBootVolume(scanBootVolumes(0x81, 0));
-        if ( hd_bvr->flags & kBVFlagNativeBoot )
-        {
-            int key = countdown("Press C to start up from CD-ROM.",
-                                kMenuTopRow, 5);
-            
-            if ( (key & 0x5f) != 'c' )
-            {
+        if (getIntForKey( kCDROMOptionKey, &optionKey )) {
+            // The key specified is a special key.
+        } else if (getValueForKey( kCDROMOptionKey, &val, &cnt) && cnt >= 1) {
+            optionKey = val[0];
+        } else {
+            // Default to F8.
+            optionKey = 0x4200;
+        }
+
+        key = countdown(prompt, kMenuTopRow, timeout);
+        if (cnt)
+            free(prompt);
+
+        clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
+
+        if (key == 0) {
+            // Boot from hard disk.
+            // Scan the original device 0x80.
+
+            BVRef hd_bvr = selectBootVolume(scanBootVolumes(0x80, 0));
+            if ( hd_bvr->flags & kBVFlagNativeBoot ) {
                 gBootVolume = hd_bvr;
                 gBIOSDev = hd_bvr->biosdev;
                 initKernBootStruct( gBIOSDev );
                 goto done;
             }
+        } else  {
+            if (optionKey < 0x100)
+                key = key & 0x5F;
+            if (key != optionKey)
+                goto done;
         }
+        gBootMode &= ~kBootModeQuiet;
+        timeout = 0;
     }
-#endif
 
     if ( gBootMode & kBootModeQuiet )
     {
@@ -520,6 +553,11 @@ getBootOptions(BOOL firstRun)
          ( countdown("Press any key to enter startup options.",
                      kMenuTopRow, timeout) == 0 ) )
     {
+        // If the user is holding down a modifier key,
+        // enter safe mode.
+        if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) {
+            gBootMode |= kBootModeSafe;
+        }
         goto done;
     }
 
@@ -622,7 +660,71 @@ done:
 extern unsigned char chainbootdev;
 extern unsigned char chainbootflag;
 
-int processBootOptions()
+BOOL
+copyArgument(const char *argName, const char *val, int cnt, char **argP, int *cntRemainingP)
+{
+    int argLen = argName ? strlen(argName) : 0;
+    int len = argLen + cnt + 1;  // +1 to account for space
+
+    if (len > *cntRemainingP) {
+        error("Warning: boot arguments too long, truncating\n");
+        return NO;
+    }
+
+    if (argName) {
+        strncpy( *argP, argName, argLen );
+        *argP += argLen;
+        *argP[0] = '=';
+        (*argP)++;
+        len++; // +1 to account for '='
+    }
+    strncpy( *argP, val, cnt );
+    *argP += cnt;
+    *argP[0] = ' ';
+    (*argP)++;
+
+    *cntRemainingP -= len;
+    return YES;
+}
+// 
+// Returns TRUE if an argument was copied, FALSE otherwise
+
+BOOL
+processBootArgument(
+                    const char *argName,      // The argument to search for
+                    const char *userString,   // Typed-in boot arguments
+                    const char *kernelFlags,  // Kernel flags from config table
+                    const char *configTable,
+                    char **argP,                // Output value
+                    int *cntRemainingP,         // Output count
+                    char *foundVal              // found value
+                    )
+{
+    const char *val;
+    int cnt;
+    BOOL found = NO;
+
+    if (getValueForBootKey(userString, argName, &val, &cnt)) {
+        // Don't copy; these values will be copied at the end of argument processing.
+        found = YES;
+    } else if (getValueForBootKey(kernelFlags, argName, &val, &cnt)) {
+        // Don't copy; these values will be copied at the end of argument processing.
+        found = YES;
+    } else if (getValueForConfigTableKey(configTable, argName, &val, &cnt)) {
+        copyArgument(argName, val, cnt, argP, cntRemainingP);
+        found = YES;
+    }
+    if (found && foundVal) {
+        strlcpy(foundVal, val, cnt+1);
+    }
+    return found;
+}
+
+// Maximum config table value size
+#define VALUE_SIZE 1024
+
+int
+processBootOptions()
 {
     const char *     cp  = gBootArgs;
     const char *     val = 0;
@@ -631,6 +733,12 @@ int processBootOptions()
     int		     userCnt;
     int              cntRemaining;
     char *           argP;
+    char             uuidStr[64];
+    BOOL             uuidSet = NO;
+    char *           configKernelFlags;
+    char *           valueBuffer;
+
+    valueBuffer = (char *)malloc(VALUE_SIZE);
 
     skipblanks( &cp );
 
@@ -654,10 +762,10 @@ int processBootOptions()
             return 1;
         }
 
-        bootArgs->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) |
+        bootInfo->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) |
                           (B_PARTITIONMASK << B_PARTITIONSHIFT));
 
-        bootArgs->kernDev |= MAKEKERNDEV(    0,
+        bootInfo->kernDev |= MAKEKERNDEV(    0,
  		         /* unit */      BIOS_DEV_UNIT(gBootVolume),
                         /* partition */ gBootVolume->part_no );
     }
@@ -680,60 +788,94 @@ int processBootOptions()
 
     gOverrideKernel = NO;
     if (( kernel = extractKernelName((char **)&cp) )) {
-        strcpy( bootArgs->bootFile, kernel );
+        strcpy( bootInfo->bootFile, kernel );
         gOverrideKernel = YES;
     } else {
         if ( getValueForKey( kKernelNameKey, &val, &cnt ) ) {
-            strlcpy( bootArgs->bootFile, val, cnt+1 );
-            if (strcmp( bootArgs->bootFile, kDefaultKernel ) != 0) {
+            strlcpy( bootInfo->bootFile, val, cnt+1 );
+            if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) {
                 gOverrideKernel = YES;
             }
         } else {
-            strcpy( bootArgs->bootFile, kDefaultKernel );
+            strcpy( bootInfo->bootFile, kDefaultKernel );
         }
     }
 
     cntRemaining = BOOT_STRING_LEN - 2;  // save 1 for NULL, 1 for space
+    argP = bootArgs->CommandLine;
+
+    // Get config table kernel flags, if not ignored.
+    if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) == TRUE ||
+            getValueForKey( kKernelFlagsKey, &val, &cnt ) == FALSE) {
+        val = "";
+        cnt = 0;
+    }
+    configKernelFlags = (char *)malloc(cnt + 1);
+    strlcpy(configKernelFlags, val, cnt + 1);
 
-    // Check to see if we need to specify root device.
-    // If user types "rd=.." on the boot line, it overrides
-    // the boot device key in the boot arguments file.
-    //
-    argP = bootArgs->bootString;
-    if ( getValueForBootKey( cp, kRootDeviceKey, &val, &cnt ) == FALSE &&
-         getValueForKey( kRootDeviceKey, &val, &cnt ) == FALSE ) {
-        if ( getValueForKey( kBootDeviceKey, &val, &cnt ) ) {
-            strcpy( argP, "rd=*" );
-            argP += 4;
-            strlcpy( argP, val, cnt+1);
-            cntRemaining -= cnt;
-            argP += cnt;
-            *argP++ = ' ';
+    if (processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, 0)) {
+        // boot-uuid was set either on the command-line
+        // or in the config file.
+        uuidSet = YES;
+    } else {
+        if (GetFSUUID(bootInfo->bootFile, uuidStr) == 0) {
+            verbose("Setting boot-uuid to: %s\n", uuidStr);
+            copyArgument(kBootUUIDKey, uuidStr, strlen(uuidStr), &argP, &cntRemaining);
+            uuidSet = YES;
         }
     }
 
-    // Check to see if we should ignore saved kernel flags.
-    if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) == FALSE) {
-        if (getValueForKey( kKernelFlagsKey, &val, &cnt ) == FALSE) {
-	    val = 0;
-	    cnt = 0;
+    if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice)) {
+        cnt = 0;
+        if ( getValueForKey( kBootDeviceKey, &val, &cnt)) {
+            valueBuffer[0] = '*';
+            cnt++;
+            strlcpy(valueBuffer + 1, val, cnt);
+            val = valueBuffer;
+        } else {
+            if (uuidSet) {
+                val = "*uuid";
+                cnt = 5;
+            } else {
+                // Don't set "rd=.." if there is no boot device key
+                // and no UUID.
+                val = "";
+                cnt = 0;
+            }
+        } 
+        if (cnt > 0) {
+            copyArgument( kRootDeviceKey, val, cnt, &argP, &cntRemaining);
         }
+        strlcpy( gRootDevice, val, (cnt + 1));
     }
 
-    // Store the merged kernel flags and boot args.
+    if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gPlatformName)) {
+        getPlatformName(gPlatformName);
+        copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining);
+    }
 
-    if (cnt > cntRemaining) {
-	error("Warning: boot arguments too long, truncated\n");
-	cnt = cntRemaining;
+    if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) &&
+        !getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt)) {
+        if (gBootMode & kBootModeSafe) {
+            copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &cntRemaining);
+        }
     }
+
+    // Store the merged kernel flags and boot args.
+
+    cnt = strlen(configKernelFlags);
     if (cnt) {
-      strncpy(argP, val, cnt);
-      argP[cnt++] = ' ';
+        if (cnt > cntRemaining) {
+            error("Warning: boot arguments too long, truncating\n");
+            cnt = cntRemaining;
+        }
+        strncpy(argP, configKernelFlags, cnt);
+        argP[cnt++] = ' ';
+        cntRemaining -= cnt;
     }
-    cntRemaining = cntRemaining - cnt;
     userCnt = strlen(cp);
     if (userCnt > cntRemaining) {
-	error("Warning: boot arguments too long, truncated\n");
+	error("Warning: boot arguments too long, truncating\n");
 	userCnt = cntRemaining;
     }
     strncpy(&argP[cnt], cp, userCnt);
@@ -745,19 +887,21 @@ int processBootOptions()
     gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt ) ) ?
                 kBootModeSafe : kBootModeNormal;
 
-    if ( getValueForKey( kPlatformKey, &val, &cnt ) ) {
-        strlcpy(gPlatformName, val, cnt + 1);
-    } else {
-        strcpy(gPlatformName, "ACPI");
+    if ( getValueForKey( kOldSafeModeFlag, &val, &cnt ) ) {
+        gBootMode = kBootModeSafe;
     }
 
     if ( getValueForKey( kMKextCacheKey, &val, &cnt ) ) {
         strlcpy(gMKextName, val, cnt + 1);
     }
 
+    free(configKernelFlags);
+    free(valueBuffer);
+
     return 0;
 }
 
+
 //==========================================================================
 // Load the help file and display the file contents on the screen.
 
diff --git a/i386/cdboot/cdboot.s b/i386/cdboot/cdboot.s
index c286b9e..deed6d8 100644
--- a/i386/cdboot/cdboot.s
+++ b/i386/cdboot/cdboot.s
@@ -42,7 +42,7 @@ DEBUG	EQU 0
 %define DebugPause(x)
 %endif
 
-kBoot2Sectors        EQU  112           ; sectors to load for boot2
+kBoot2Sectors        EQU  126           ; sectors to load for boot2
 kBoot2Address        EQU  0x0200        ; boot2 load address
 kBoot2Segment        EQU  0x2000        ; boot2 load segment
 	
diff --git a/i386/libsa/Makefile b/i386/libsa/Makefile
index 211b28a..7b7d680 100644
--- a/i386/libsa/Makefile
+++ b/i386/libsa/Makefile
@@ -6,10 +6,11 @@ UTILDIR = ../util
 INSTALL_SA_DIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone
 INSTALL_MD_DIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/machdep/i386
 
-OPTIM = -Os
+OPTIM = -Os -Oz
 CFLAGS	= $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
 	      -fno-builtin -static -fomit-frame-pointer \
-	      -mpreferred-stack-boundary=2 -fno-align-functions
+	      -mpreferred-stack-boundary=2 -fno-align-functions \
+	      -mno-sse2 -mfpmath=387
 
 INC = -I. -I$(SYMROOT) -I$(UTILDIR)
 ifneq "" "$(wildcard /bin/mkdirs)"
diff --git a/i386/libsa/memory.h b/i386/libsa/memory.h
index a5dbece..bb473dc 100644
--- a/i386/libsa/memory.h
+++ b/i386/libsa/memory.h
@@ -67,11 +67,11 @@
 #define KERNEL_ADDR       0x00100000   // 64M kernel + drivers
 #define KERNEL_LEN        0x04000000
 
-#define ZALLOC_ADDR       0x04100000   // 47M zalloc area
-#define ZALLOC_LEN        0x02F00000
+#define ZALLOC_ADDR       0x04100000   // 39M zalloc area
+#define ZALLOC_LEN        0x02700000
 
-#define LOAD_ADDR         0x07000000   // 16M File load buffer
-#define LOAD_LEN          0x01000000
+#define LOAD_ADDR         0x06800000   // 24M File load buffer
+#define LOAD_LEN          0x01800000
 
 #define TFTP_ADDR         LOAD_ADDR   // tftp download buffer
 #define TFTP_LEN          LOAD_LEN
diff --git a/i386/libsa/string.c b/i386/libsa/string.c
index 682abfe..a65a6e4 100644
--- a/i386/libsa/string.c
+++ b/i386/libsa/string.c
@@ -27,7 +27,7 @@
 
 void * memset(void * dst, int val, size_t len)
 {
-    asm( "rep; stosb"
+    asm volatile ( "rep; stosb"
        : "=c" (len), "=D" (dst)
        : "0" (len), "1" (dst), "a" (val)
        : "memory" );
@@ -38,7 +38,7 @@ void * memset(void * dst, int val, size_t len)
 #if 0
 void * memcpy(void * dst, const void * src, size_t len)
 {
-    asm( "rep; movsb"
+    asm volatile ( "rep; movsb"
        : "=c" (len), "=D" (dst), "=S" (src)
        : "0" (len), "1" (dst), "2" (src)
        : "memory" );
@@ -59,7 +59,7 @@ void bzero(void * dst, size_t len)
 #else
 void * memcpy(void * dst, const void * src, size_t len)
 {
-    asm( "cld                  \n\t"
+    asm volatile ( "cld                  \n\t"
          "movl %%ecx, %%edx    \n\t"
          "shrl $2, %%ecx       \n\t"
          "rep; movsl           \n\t"
@@ -75,7 +75,7 @@ void * memcpy(void * dst, const void * src, size_t len)
 
 void bcopy(const void * src, void * dst, size_t len)
 {
-    asm( "cld                  \n\t"
+    asm volatile ( "cld                  \n\t"
          "movl %%ecx, %%edx    \n\t"
          "shrl $2, %%ecx       \n\t"
          "rep; movsl           \n\t"
@@ -89,7 +89,7 @@ void bcopy(const void * src, void * dst, size_t len)
 
 void bzero(void * dst, size_t len)
 {
-    asm( "xorl %%eax, %%eax    \n\t"
+    asm volatile ( "xorl %%eax, %%eax    \n\t"
          "cld                  \n\t"
          "movl %%ecx, %%edx    \n\t"
          "shrl $2, %%ecx       \n\t"
diff --git a/i386/libsa/zalloc.c b/i386/libsa/zalloc.c
index 51162eb..8005a01 100644
--- a/i386/libsa/zalloc.c
+++ b/i386/libsa/zalloc.c
@@ -64,7 +64,7 @@ size_t zalloced_size;
 static void malloc_error(char *addr, size_t size)
 {
 #ifdef i386
-    asm("hlt");
+    asm volatile ("hlt");
 #endif
 }
 
@@ -177,7 +177,7 @@ void free(void * pointer)
 #if i386    
         // Get return address of our caller,
         // in case we have to report an error below.
-        asm("movl %%esp, %%eax\n\t"
+        asm volatile ("movl %%esp, %%eax\n\t"
             "subl $4, %%eax\n\t"
             "movl 0(%%eax), %%eax" : "=a" (rp) );
 #else
diff --git a/i386/libsaio/Makefile b/i386/libsaio/Makefile
index 273cad7..517f141 100644
--- a/i386/libsaio/Makefile
+++ b/i386/libsaio/Makefile
@@ -7,12 +7,13 @@ LIBSADIR = ../libsa
 INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone
 #SYMROOT=
 
-OPTIM = -Os
-CFLAGS	= $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
+OPTIM = -Os -Oz
+CFLAGS	= $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \
     -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \
     -DRCZ_COMPRESSED_FILE_SUPPORT \
     -fno-builtin -static -fomit-frame-pointer \
-    -mpreferred-stack-boundary=2 -fno-align-functions
+    -mpreferred-stack-boundary=2 -fno-align-functions \
+    -mno-sse2 -mfpmath=387
 DEFINES=
 CONFIG = hd
 INC = -I../rcz -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR)
@@ -30,10 +31,11 @@ VPATH = $(OBJROOT):$(SYMROOT)
 
 SAIO_OBJS = table.o asm.o bios.o biosfn.o \
 	disk.o sys.o cache.o bootstruct.o \
-	ufs.o ufs_byteorder.o \
 	stringTable.o load.o memory.o misc.o \
+	ufs.o ufs_byteorder.o \
 	vbe.o nbp.o hfs.o hfs_compare.o \
-	xml.o ntfs.o msdos.o
+	xml.o ntfs.o msdos.o md5c.o device_tree.o
+
 
 SAIO_EXTERN_OBJS = console.o
 
diff --git a/i386/libsaio/asm.s b/i386/libsaio/asm.s
index 367a9ea..a9bbe9d 100644
--- a/i386/libsaio/asm.s
+++ b/i386/libsaio/asm.s
@@ -31,6 +31,9 @@
 /*
  * HISTORY
  * $Log: asm.s,v $
+ * Revision 1.8  2005/06/24 22:47:12  curtisg
+ * Merging changes for 4159531 to pass data to the kernel in EFI format.
+ *
  * Revision 1.7  2004/05/13 17:58:38  curtisg
  * Integrating:
  * <rdar://problem/3094680>: (Silent boot)
@@ -293,7 +296,7 @@ xreal:
 // halt()
 //
 LABEL(_halt)
-    hlt
+    call    _bgetc
     jmp     _halt
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/i386/libsaio/bios.h b/i386/libsaio/bios.h
index a29708c..f75cc8f 100644
--- a/i386/libsaio/bios.h
+++ b/i386/libsaio/bios.h
@@ -78,4 +78,28 @@ typedef struct {
 
 #define BASE_HD_DRIVE 0x80
 
+#if 0
+/* 
+ * ACPI defined memory range types.
+ */
+enum {
+    kMemoryRangeUsable   = 1,    // RAM usable by the OS.
+    kMemoryRangeReserved = 2,    // Reserved. (Do not use)
+    kMemoryRangeACPI     = 3,    // ACPI tables. Can be reclaimed.
+    kMemoryRangeNVS      = 4,    // ACPI NVS memory. (Do not use)
+
+    /* Undefined types should be treated as kMemoryRangeReserved */
+}; 
+#endif
+
+/*
+ * Memory range descriptor.
+ */
+typedef struct MemoryRange {
+    unsigned long long base;     // 64-bit base address
+    unsigned long long length;   // 64-bit length in bytes
+    unsigned long      type;     // type of memory range
+    unsigned long      reserved;
+} MemoryRange;
+
 #endif /* !__LIBSAIO_BIOS_H */
diff --git a/i386/libsaio/biosfn.c b/i386/libsaio/biosfn.c
index 2c9ab4f..7c0a3f2 100644
--- a/i386/libsaio/biosfn.c
+++ b/i386/libsaio/biosfn.c
@@ -87,14 +87,11 @@ unsigned long getMemoryMap( MemoryRange *   rangeArray,
     #define kMemoryMapSignature  'SMAP'
     #define kDescriptorSizeMin   20
 
-    MemoryRange *        range = rangeArray;
+    MemoryRange *        range = (MemoryRange *)BIOS_ADDR;
     unsigned long        count = 0;
     unsigned long long   conMemSize = 0;
     unsigned long long   extMemSize = 0;
 
-    // The memory pointed by the rangeArray must reside within the
-    // first megabyte.
-    //
     // Prepare for the INT15 E820h call. Each call returns a single
     // memory range. A continuation value is returned that must be
     // provided on a subsequent call to fetch the next range.
@@ -106,6 +103,10 @@ unsigned long getMemoryMap( MemoryRange *   rangeArray,
     // Some BIOSes will simply ignore the value of ECX on entry.
     // Probably best to keep its value at 20 to avoid surprises.
 
+    //printf("Get memory map 0x%x, %d\n", rangeArray);getc();
+    if (maxRangeCount > (BIOS_LEN / sizeof(MemoryRange))) {
+        maxRangeCount = (BIOS_LEN / sizeof(MemoryRange));
+    }
     bb.ebx.rx = 0;  // Initial continuation value must be zero.
 
     while ( count < maxRangeCount )
@@ -122,7 +123,11 @@ unsigned long getMemoryMap( MemoryRange *   rangeArray,
 
         if ( bb.flags.cf
         ||   bb.eax.rx != kMemoryMapSignature
-        ||   bb.ecx.rx != kDescriptorSizeMin ) break;
+        ||   bb.ecx.rx != kDescriptorSizeMin ) {
+            //printf("Got an error %x %x %x\n", bb.flags.cf,
+            //       bb.eax.rx, bb.ecx.rx);
+            break;
+        }
 
         // Tally up the conventional/extended memory sizes.
 
@@ -146,17 +151,24 @@ unsigned long getMemoryMap( MemoryRange *   rangeArray,
 
         // Is this the last address range?
 
-        if ( bb.ebx.rx == 0 ) break;
+        if ( bb.ebx.rx == 0 ) {
+            //printf("last range\n");
+            break;
+        }
     }
     *conMemSizePtr = conMemSize / 1024;  // size in KB
     *extMemSizePtr = extMemSize  / 1024;  // size in KB
 
+    // Copy out data
+    bcopy((char *)BIOS_ADDR, rangeArray, ((char *)range - (char *)BIOS_ADDR));
+
 #if DEBUG
     {
-        for (range = rangeArray; range->length != 0; range++) {
-        printf("range: type %d, base 0x%x, length 0x%x\n",
-               range->type, (unsigned int)range->base, (unsigned int)range->length); getc();
-
+        int i;
+        printf("%d total ranges\n", count);getc();
+        for (i=0, range = rangeArray; i<count; i++, range++) {
+            printf("range: type %d, base 0x%x, length 0x%x\n",
+                   range->type, (unsigned int)range->base, (unsigned int)range->length); getc();
         }
     }
 #endif
@@ -554,6 +566,7 @@ int get_drive_info(int drive, struct driveInfo *dp)
 #if DEBUG
     print_drive_info(di);
     printf("uses_ebios = 0x%x\n", dp->uses_ebios);
+    printf("result %d\n", ret);
     printf("press a key->\n");getc();
 #endif
 
diff --git a/i386/libsaio/bootstruct.c b/i386/libsaio/bootstruct.c
index 18c9ccd..e42b912 100644
--- a/i386/libsaio/bootstruct.c
+++ b/i386/libsaio/bootstruct.c
@@ -29,104 +29,76 @@
 #include "libsaio.h"
 #include "bootstruct.h"
 
-// CMOS access ports in I/O space.
-//
-#define CMOSADDR    0x70
-#define CMOSDATA    0x71
-#define HDTYPE      0x12
-
 /*==========================================================================
- * Returns the number of active ATA drives since these will increment the
- * bios device numbers of SCSI drives.
- */
-static int countIDEDisks()
-{
-    int            count = 0;
-    unsigned short hdtype;
-
-#if DEBUG
-    struct driveParameters param;
-
-    printf("Reading drive parameters...\n");
-    readDriveParameters(0x80, &param);
-    printf("%d fixed disk drive(s) installed\n", param.totalDrives);
-    for (count = 0; count < 256; count++)
-    {
-        if (readDriveParameters(count + 0x80, &param))
-            break;
-        else
-        {
-            printf("Drive %d: %d cyls, %d heads, %d sectors\n",
-                   count, param.cylinders, param.heads, param.sectors);
-        }
-    }
-    outb(CMOSADDR, 0x11);
-    printf("CMOS addr 0x11 = %x\n",inb(CMOSDATA));
-    outb(CMOSADDR, 0x12);
-    printf("CMOS addr 0x12 = %x\n",inb(CMOSDATA));
-    return count;
-#endif
-
-    outb( CMOSADDR, HDTYPE );
-    hdtype = (unsigned short) inb( CMOSDATA );
-
-    if (hdtype & 0xF0) count++;
-    if (hdtype & 0x0F) count++;
-    return count;
-}
-
-/*==========================================================================
- * Initialize the 'kernBootStruct'. A structure of parameters passed to
+ * Initialize the structure of parameters passed to
  * the kernel by the booter.
  */
 
-KernelBootArgs_t *bootArgs;
+boot_args         *bootArgs;
+PrivateBootInfo_t *bootInfo;
+Node              *gMemoryMapNode;
+
+static char platformName[64];
 
 void initKernBootStruct( int biosdev )
 {
+    Node *node;
+    int nameLen;
     static int init_done = 0;
 
-    bootArgs = (KernelBootArgs_t *)KERNSTRUCT_ADDR;
-
     if ( !init_done )
     {
-        bzero(bootArgs, sizeof(KernelBootArgs_t));
+        bootArgs = (boot_args *)malloc(sizeof(boot_args));
+        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(bootInfo, sizeof(PrivateBootInfo_t));
 
         // Get system memory map. Also update the size of the
         // conventional/extended memory for backwards compatibility.
 
-        bootArgs->memoryMapCount =
-            getMemoryMap( bootArgs->memoryMap, kMemoryMapCountMax,
-                          (unsigned long *) &bootArgs->convmem,
-                          (unsigned long *) &bootArgs->extmem );
+        bootInfo->memoryMapCount =
+            getMemoryMap( bootInfo->memoryMap, kMemoryMapCountMax,
+                          (unsigned long *) &bootInfo->convmem,
+                          (unsigned long *) &bootInfo->extmem );
 
-        if ( bootArgs->memoryMapCount == 0 )
+        if ( bootInfo->memoryMapCount == 0 )
         {
             // BIOS did not provide a memory map, systems with
             // discontiguous memory or unusual memory hole locations
             // may have problems.
 
-            bootArgs->convmem = getConventionalMemorySize();
-            bootArgs->extmem  = getExtendedMemorySize();
+            bootInfo->convmem = getConventionalMemorySize();
+            bootInfo->extmem  = getExtendedMemorySize();
         }
 
-        bootArgs->magicCookie  = KERNBOOTMAGIC;
-        bootArgs->configEnd    = bootArgs->config;
-        bootArgs->graphicsMode = TEXT_MODE;
+        bootInfo->configEnd    = bootInfo->config;
+        bootArgs->Video.v_display = VGA_TEXT_MODE;
         
-	/* New style */
-	/* XXX initialize bootArgs here */
+        DT__Initialize();
 
-        init_done = 1;
-    }
+        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);
 
-    // Get number of ATA devices.
+        gMemoryMapNode = DT__FindNode("/chosen/memory-map", true);
 
-    bootArgs->numDrives = countIDEDisks();
+        bootArgs->Version  = kBootArgsVersion;
+        bootArgs->Revision = kBootArgsRevision;
+
+        init_done = 1;
+    }
 
     // Update kernDev from biosdev.
 
-    bootArgs->kernDev = biosdev;
+    bootInfo->kernDev = biosdev;
 }
 
 
@@ -136,7 +108,69 @@ void
 reserveKernBootStruct(void)
 {
     void *oldAddr = bootArgs;
-    bootArgs = (KernelBootArgs_t *)AllocateKernelMemory(sizeof(KERNBOOTSTRUCT));
-    bcopy(oldAddr, bootArgs, sizeof(KernelBootArgs_t));
+    bootArgs = (boot_args *)AllocateKernelMemory(sizeof(boot_args));
+    bcopy(oldAddr, bootArgs, sizeof(boot_args));
 }
 
+void
+finalizeBootStruct(void)
+{
+    uint32_t size;
+    void *addr;
+    int i;
+    EfiMemoryRange *memoryMap;
+    MemoryRange *range;
+    int memoryMapCount = bootInfo->memoryMapCount;
+
+    if (memoryMapCount == 0) {
+        // XXX could make a two-part map here
+        stop("Unable to convert memory map into proper format\n");
+    }
+
+    // convert memory map to boot_args memory map
+    memoryMap = (EfiMemoryRange *)AllocateKernelMemory(sizeof(EfiMemoryRange) * memoryMapCount);
+    bootArgs->MemoryMap = memoryMap;
+    bootArgs->MemoryMapSize = sizeof(EfiMemoryRange) * memoryMapCount;
+    bootArgs->MemoryMapDescriptorSize = sizeof(EfiMemoryRange);
+    bootArgs->MemoryMapDescriptorVersion = 0;
+
+    for (i=0; i<memoryMapCount; i++, memoryMap++) {
+        range = &bootInfo->memoryMap[i];
+        switch(range->type) {
+        case kMemoryRangeACPI:
+            memoryMap->Type = kEfiACPIReclaimMemory;
+            break;
+        case kMemoryRangeNVS:
+            memoryMap->Type = kEfiACPIMemoryNVS;
+            break;
+        case kMemoryRangeUsable:
+            memoryMap->Type = kEfiConventionalMemory;
+            break;
+        case kMemoryRangeReserved:
+        default:
+            memoryMap->Type = kEfiReservedMemoryType;
+            break;
+        }
+        memoryMap->PhysicalStart = range->base;
+        memoryMap->VirtualStart = range->base;
+        memoryMap->NumberOfPages = range->length >> I386_PGSHIFT;
+        memoryMap->Attribute = 0;
+    }
+
+    // copy bootFile into device tree
+    // XXX
+
+    // add PCI info somehow into device tree
+    // XXX
+
+    // Flatten device tree
+    DT__FlattenDeviceTree(0, &size);
+    addr = (void *)AllocateKernelMemory(size);
+    if (addr == 0) {
+        stop("Couldn't allocate device tree\n");
+    }
+    
+    DT__FlattenDeviceTree((void **)&addr, &size);
+    bootArgs->deviceTreeP = (void *)addr;
+    bootArgs->deviceTreeLength = size;
+}
diff --git a/i386/libsaio/bootstruct.h b/i386/libsaio/bootstruct.h
index e67002a..32711a6 100644
--- a/i386/libsaio/bootstruct.h
+++ b/i386/libsaio/bootstruct.h
@@ -22,6 +22,89 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 
+#ifndef __BOOTSTRUCT_H
+#define __BOOTSTRUCT_H
+
 #include <pexpert/i386/boot.h>
 
-extern KernelBootArgs_t *bootArgs;
+#include "bios.h"
+#include "device_tree.h"
+
+extern boot_args *bootArgs;
+extern Node *gMemoryMapNode;
+
+/*
+ * Maximum number of boot drivers that can be loaded.
+ */
+#define NDRIVERS  500
+
+#define CONFIG_SIZE (12 * 4096)
+
+#define kMemoryMapCountMax 40
+
+/*
+ * PCI bus information.
+ */
+typedef struct _PCI_bus_info_t {
+    union {
+        struct {
+            unsigned char configMethod1 :1;
+            unsigned char configMethod2 :1;
+            unsigned char               :2;
+            unsigned char specialCycle1 :1;
+            unsigned char specialCycle2 :1;
+        } s;
+        unsigned char d;
+    } u_bus;
+    unsigned char maxBusNum;
+    unsigned char majorVersion;
+    unsigned char minorVersion;
+    unsigned char BIOSPresent;
+} PCI_bus_info_t;
+
+typedef struct {
+    unsigned long address;  // address where driver was loaded
+    unsigned long size;     // number of bytes
+    unsigned long type;     // driver type
+} driver_config_t;
+
+/*
+ * INT15, E820h - Query System Address Map.
+ *
+ * Documented in ACPI Specification Rev 2.0,
+ * Chapter 15 (System Address Map Interfaces).
+ */
+
+/*
+ * ACPI defined memory range types.
+ */
+enum {
+    kMemoryRangeUsable   = 1,    // RAM usable by the OS.
+    kMemoryRangeReserved = 2,    // Reserved. (Do not use)
+    kMemoryRangeACPI     = 3,    // ACPI tables. Can be reclaimed.
+    kMemoryRangeNVS      = 4,    // ACPI NVS memory. (Do not use)
+
+    /* Undefined types should be treated as kMemoryRangeReserved */
+};
+
+typedef struct PrivateBootInfo {
+    int              kernDev;                      // device kernel was fetched from
+
+    int              convmem;                      // conventional memory
+    int              extmem;                       // extended memory
+    int              numBootDrivers;               // number of drivers loaded
+    char             bootFile[128];                // kernel file name
+
+    unsigned long    memoryMapCount;
+    MemoryRange      memoryMap[kMemoryMapCountMax];
+
+    PCI_bus_info_t   pciInfo;
+
+    driver_config_t  driverConfig[NDRIVERS];
+    char *           configEnd;                    // pointer to end of config files
+    char             config[CONFIG_SIZE];
+} PrivateBootInfo_t;
+
+extern PrivateBootInfo_t *bootInfo;
+
+#endif /* __BOOTSTRUCT_H */
diff --git a/i386/libsaio/cache.c b/i386/libsaio/cache.c
index 52a32e4..8b79dbc 100644
--- a/i386/libsaio/cache.c
+++ b/i386/libsaio/cache.c
@@ -100,8 +100,8 @@ void CacheInit( CICell ih, long blockSize )
 long CacheRead( CICell ih, char * buffer, long long offset,
 	            long length, long cache )
 {
-	long       cnt, oldestEntry = 0, oldestTime, loadCache = 0;
-	CacheEntry *entry;
+    long       cnt, oldestEntry = 0, oldestTime, loadCache = 0;
+    CacheEntry *entry;
 
     // See if the data can be cached.
     if (cache && (gCacheIH == ih) && (length == gCacheBlockSize)) {
diff --git a/i386/libsaio/console.c b/i386/libsaio/console.c
index 3922373..d6bdfac 100644
--- a/i386/libsaio/console.c
+++ b/i386/libsaio/console.c
@@ -96,7 +96,7 @@ int getchar()
 int printf(const char * fmt, ...)
 {
     va_list ap;
-    if (bootArgs->graphicsMode != TEXT_MODE) return -1;
+    if (bootArgs->Video.v_display != VGA_TEXT_MODE) return -1;
     va_start(ap, fmt);
     prf(fmt, ap, putchar, 0);
     va_end(ap);
@@ -126,8 +126,14 @@ int error(const char * fmt, ...)
     return(0);
 }
 
-void stop(const char * msg)
+void stop(const char * fmt, ...)
 {
-    error("\n%s\n", msg);
+    va_list ap;
+
+    printf("\n");
+    va_start(ap, fmt);
+    prf(fmt, ap, putchar, 0);
+    va_end(ap);
+    printf("\n");
     halt();
 }
diff --git a/i386/libsaio/device_tree.c b/i386/libsaio/device_tree.c
new file mode 100644
index 0000000..067dea0
--- /dev/null
+++ b/i386/libsaio/device_tree.c
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc.  All Rights Reserved.
+ */
+
+#if 1
+/*
+ 
+ Structures for a Flattened Device Tree 
+ */
+
+#define kPropNameLength 32
+
+typedef struct DeviceTreeNodeProperty {
+    char                name[kPropNameLength];  // NUL terminated property name
+    unsigned long       length;         // Length (bytes) of folloing prop value
+                                        //  unsigned long       value[1];       // Variable length value of property
+                                        // Padded to a multiple of a longword?
+} DeviceTreeNodeProperty;
+
+typedef struct OpaqueDTEntry {
+    unsigned long       nProperties;    // Number of props[] elements (0 => end)
+    unsigned long       nChildren;      // Number of children[] elements
+                                        //  DeviceTreeNodeProperty      props[];// array size == nProperties
+                                        //  DeviceTreeNode      children[];     // array size == nChildren
+} DeviceTreeNode;
+
+typedef char DTPropertyNameBuf[32];
+/* Entry Name Definitions (Entry Names are C-Strings)*/
+enum {
+    kDTMaxEntryNameLength           = 31    /* Max length of a C-String Entry Name (terminator not included) */
+};
+
+/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
+typedef char DTEntryNameBuf[32];
+#endif
+
+#include "libsaio.h"
+#include "device_tree.h"
+
+#if DEBUG
+#define DPRINTF(args...) printf(args)
+#else
+#define DPRINTF(args...)
+#endif
+
+
+void
+DT__PrintTree(Node *node);
+
+#define RoundToLong(x)	(((x) + 3) & ~3)
+
+static struct _DTSizeInfo {
+    uint32_t numNodes;
+    uint32_t numProperties;
+    uint32_t totalPropertySize;
+} DTInfo;
+
+#define kAllocSize 4096
+
+static Node *rootNode;
+
+static Node *freeNodes, *allocedNodes;
+static Property *freeProperties, *allocedProperties;
+
+Property *
+DT__AddProperty(Node *node, char *name, uint32_t length, void *value)
+{
+    Property *prop;
+
+    DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node), name, length, value);
+    if (freeProperties == NULL) {
+        void *buf = malloc(kAllocSize);
+        int i;
+        
+        DPRINTF("Allocating more free properties\n");
+        if (buf == 0) return 0;
+        bzero(buf, kAllocSize);
+        // Use the first property to record the allocated buffer
+        // for later freeing.
+        prop = (Property *)buf;
+        prop->next = allocedProperties;
+        allocedProperties = prop;
+        prop->value = buf;
+        prop++;
+        for (i=1; i<(kAllocSize / sizeof(Property)); i++) {
+            prop->next = freeProperties;
+            freeProperties = prop;
+            prop++;
+        }
+    }
+    prop = freeProperties;
+    freeProperties = prop->next;
+
+    prop->name = name;
+    prop->length = length;
+    prop->value = value;
+
+    // Always add to end of list
+    if (node->properties == 0) {
+        node->properties = prop;
+    } else {
+        node->last_prop->next = prop;
+    }
+    node->last_prop = prop;
+    prop->next = 0;
+
+    DPRINTF("Done [0x%x]\n", prop);
+    
+    DTInfo.numProperties++;
+    DTInfo.totalPropertySize += RoundToLong(length);
+
+    return prop;
+}
+
+Node *
+DT__AddChild(Node *parent, char *name)
+{
+    Node *node;
+
+    if (freeNodes == NULL) {
+        void *buf = malloc(kAllocSize);
+        int i;
+        
+        DPRINTF("Allocating more free nodes\n");
+        if (buf == 0) return 0;
+        bzero(buf, kAllocSize);
+        node = (Node *)buf;
+        // Use the first node to record the allocated buffer
+        // for later freeing.
+        node->next = allocedNodes;
+        allocedNodes = node;
+        node->children = (Node *)buf;
+        node++;
+        for (i=1; i<(kAllocSize / sizeof(Node)); i++) {
+            node->next = freeNodes;
+            freeNodes = node;
+            node++;
+        }
+    }
+    DPRINTF("DT__AddChild(0x%x, '%s')\n", parent, name);
+    node = freeNodes;
+    freeNodes = node->next;
+    DPRINTF("Got free node 0x%x\n", node);
+    DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node->properties, node->children, node->next);
+
+    if (parent == NULL) {
+        rootNode = node;
+        node->next = 0;
+    } else {
+        node->next = parent->children;
+        parent->children = node;
+    }
+    DTInfo.numNodes++;
+    DT__AddProperty(node, "name", strlen(name) + 1, name);
+    return node;
+}
+
+void
+DT__FreeProperty(Property *prop)
+{
+    prop->next = freeProperties;
+    freeProperties = prop;
+}
+void
+DT__FreeNode(Node *node)
+{
+    node->next = freeNodes;
+    freeNodes = node;
+}
+
+void
+DT__Initialize(void)
+{
+    DPRINTF("DT__Initialize\n");
+    
+    freeNodes = 0;
+    allocedNodes = 0;
+    freeProperties = 0;
+    allocedProperties = 0;
+    
+    DTInfo.numNodes = 0;
+    DTInfo.numProperties = 0;
+    DTInfo.totalPropertySize = 0;
+    
+    rootNode = DT__AddChild(NULL, "/");
+    DPRINTF("DT__Initialize done\n");
+}
+
+/*
+ * Free up memory used by in-memory representation
+ * of device tree.
+ */
+void
+DT__Finalize(void)
+{
+    Node *node;
+    Property *prop;
+
+    DPRINTF("DT__Finalize\n");
+    for (prop = allocedProperties; prop != NULL; prop = prop->next) {
+        free(prop->value);
+    }
+    allocedProperties = NULL;
+    freeProperties = NULL;
+
+    for (node = allocedNodes; node != NULL; node = node->next) {
+        free((void *)node->children);
+    }
+    allocedNodes = NULL;
+    freeNodes = NULL;
+    rootNode = NULL;
+    
+    // XXX leaks any created strings
+
+    DTInfo.numNodes = 0;
+    DTInfo.numProperties = 0;
+    DTInfo.totalPropertySize = 0;
+}
+
+static void *
+FlattenNodes(Node *node, void *buffer)
+{
+    Property *prop;
+    DeviceTreeNode *flatNode;
+    DeviceTreeNodeProperty *flatProp;
+    int count;
+
+    if (node == 0) return buffer;
+
+    flatNode = (DeviceTreeNode *)buffer;
+    buffer += sizeof(DeviceTreeNode);
+
+    for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next) {
+        flatProp = (DeviceTreeNodeProperty *)buffer;
+        strcpy(flatProp->name, prop->name);
+        flatProp->length = prop->length;
+        buffer += sizeof(DeviceTreeNodeProperty);
+        bcopy(prop->value, buffer, prop->length);
+        buffer += RoundToLong(prop->length);
+    }
+    flatNode->nProperties = count;
+
+    for (count = 0, node = node->children; node != 0; count++, node = node->next) {
+        buffer = FlattenNodes(node, buffer);
+    }
+    flatNode->nChildren = count;
+
+    return buffer;
+}
+
+/*
+ * Flatten the in-memory representation of the device tree
+ * into a binary DT block.
+ * To get the buffer size needed, call with result = 0.
+ * To have a buffer allocated for you, call with *result = 0.
+ * To use your own buffer, call with *result = &buffer.
+ */
+
+void
+DT__FlattenDeviceTree(void **buffer_p, uint32_t *length)
+{
+    uint32_t totalSize;
+    void *buf;
+
+    DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length);
+    if (buffer_p) DT__PrintTree(rootNode);
+    
+    totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) + 
+        DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) +
+        DTInfo.totalPropertySize;
+
+    DPRINTF("Total size 0x%x\n", totalSize);
+    if (buffer_p != 0) {
+        if (totalSize == 0) {
+            buf = 0;
+        } else {
+            if (*buffer_p == 0) {
+                buf = malloc(totalSize);
+            } else {
+                buf = *buffer_p;
+            }
+            bzero(buf, totalSize);
+            
+            FlattenNodes(rootNode, buf);
+        }
+        *buffer_p = buf;
+    }
+    if (length)
+        *length = totalSize;
+}
+
+char *
+DT__GetName(Node *node)
+{
+    Property *prop;
+
+    //DPRINTF("DT__GetName(0x%x)\n", node);
+    //DPRINTF("Node properties = 0x%x\n", node->properties);
+    for (prop = node->properties; prop; prop = prop->next) {
+        //DPRINTF("Prop '%s'\n", prop->name);
+        if (strcmp(prop->name, "name") == 0) {
+            return prop->value;
+        }
+    }
+    //DPRINTF("DT__GetName returns 0\n");
+    return "(null)";
+}
+
+Node *
+DT__FindNode(char *path, bool createIfMissing)
+{
+    Node *node, *child;
+    DTPropertyNameBuf nameBuf;
+    char *bp;
+    int i;
+
+    DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);
+    
+    // Start at root
+    node = rootNode;
+    DPRINTF("root = 0x%x\n", rootNode);
+
+    while (node) {
+        // Skip leading slash
+        while (*path == '/') path++;
+
+        for (i=0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++) *bp = *path;
+        *bp = '\0';
+
+        if (nameBuf[0] == '\0') {
+            // last path entry
+            break;
+        }
+        DPRINTF("Node '%s'\n", nameBuf);
+
+        for (child = node->children; child != 0; child = child->next) {
+            DPRINTF("Child 0x%x\n", child);
+            if (strcmp(DT__GetName(child), nameBuf) == 0) {
+                break;
+            }
+        }
+        if (child == 0 && createIfMissing) {
+            DPRINTF("Creating node\n");
+            char *str = malloc(strlen(nameBuf) + 1);
+            // XXX this will leak
+            strcpy(str, nameBuf);
+
+            child = DT__AddChild(node, str);
+        }
+        node = child;
+    }
+    return node;
+}
+
+void
+DT__PrintNode(Node *node, int level)
+{
+    char spaces[10], *cp = spaces;
+    Property *prop;
+
+    if (level > 9) level = 9;
+    while (level--) *cp++ = ' ';
+    *cp = '\0';
+
+    printf("%s===Node===\n", spaces);
+    for (prop = node->properties; prop; prop = prop->next) {
+        char c = *((char *)prop->value);
+        if (prop->length < 64 && (
+            strcmp(prop->name, "name") == 0 || 
+            (c >= '0' && c <= '9') ||
+            (c >= 'a' && c <= 'z') ||
+            (c >= 'A' && c <= 'Z') || c == '_')) {
+            printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);
+        } else {
+            printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);
+        }
+    }
+    printf("%s==========\n", spaces);
+}
+
+static void
+_PrintTree(Node *node, int level)
+{
+    DT__PrintNode(node, level);
+    level++;
+    for (node = node->children; node; node = node->next)
+        _PrintTree(node, level);
+}
+
+void
+DT__PrintTree(Node *node)
+{
+    if (node == 0) node = rootNode;
+    _PrintTree(node, 0);
+}
+
+#if DEBUG
+
+void
+DT__PrintFlattenedNode(DTEntry entry, int level)
+{
+    char spaces[10], *cp = spaces;
+    DTPropertyIterator	                propIter;
+    char *name;
+    void *prop;
+    int propSize;
+
+    if (level > 9) level = 9;
+    while (level--) *cp++ = ' ';
+    *cp = '\0';
+
+    printf("%s===Entry %p===\n", spaces, entry);
+    if (kSuccess != DTCreatePropertyIterator(entry, &propIter)) {
+        printf("Couldn't create property iterator\n");
+        return;
+    }
+    while( kSuccess == DTIterateProperties( propIter, &name)) {
+        if(  kSuccess != DTGetProperty( entry, name, &prop, &propSize ))
+            continue;
+        printf("%s Property %s = %s\n", spaces, name, prop);
+    }
+    DTDisposePropertyIterator(propIter);
+
+    printf("%s==========\n", spaces);
+}
+
+static void
+_PrintFlattenedTree(DTEntry entry, int level)
+{
+    DTEntryIterator entryIter;
+
+    PrintFlattenedNode(entry, level);
+
+    if (kSuccess != DTCreateEntryIterator(entry, &entryIter)) {
+            printf("Couldn't create entry iterator\n");
+            return;
+    }
+    level++;
+    while (kSuccess == DTIterateEntries( entryIter, &entry )) {
+        _PrintFlattenedTree(entry, level);
+    }
+    DTDisposeEntryIterator(entryIter);
+}
+
+void
+DT__PrintFlattenedTree(DTEntry entry)
+{
+    _PrintFlattenedTree(entry, 0);
+}
+
+
+int
+main(int argc, char **argv)
+{
+    DTEntry                             dtEntry;
+    DTPropertyIterator	                propIter;
+    DTEntryIterator                     entryIter;
+    void				*prop;
+    int					propSize;
+    char				*name;
+    void *flatTree;
+    uint32_t flatSize;
+
+    Node *node;
+
+    node = AddChild(NULL, "device-tree");
+    AddProperty(node, "potato", 4, "foo");
+    AddProperty(node, "chemistry", 4, "bar");
+    AddProperty(node, "physics", 4, "baz");
+
+    node = AddChild(node, "dev");
+    AddProperty(node, "one", 4, "one");
+    AddProperty(node, "two", 4, "two");
+    AddProperty(node, "three", 6, "three");
+
+    node = AddChild(rootNode, "foo");
+    AddProperty(node, "aaa", 4, "aab");
+    AddProperty(node, "bbb", 4, "bbc");
+    AddProperty(node, "cccc", 6, "ccccd");
+
+    node = FindNode("/this/is/a/test", 1);
+    AddProperty(node, "dddd", 12, "abcdefghijk");
+
+    printf("In-memory tree:\n\n");
+
+    PrintTree(rootNode);
+
+    FlattenDeviceTree(&flatTree, &flatSize);
+
+    printf("Flat tree = %p, size %d\n", flatTree, flatSize);
+
+    dtEntry = (DTEntry)flatTree;
+
+    printf("\n\nPrinting flat tree\n\n");
+
+    DTInit(dtEntry);
+
+    PrintFlattenedTree((DTEntry)flatTree);
+#if 0
+        printf("=== Entry %p ===\n", dtEntry);
+        if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) {
+            printf("Couldn't create property iterator\n");
+            return 1;
+        }
+        while( kSuccess == DTIterateProperties( propIter, &name)) {
+            if(  kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
+                continue;
+            printf(" Property %s = %s\n", name, prop);
+        }
+        DTDisposePropertyIterator(propIter);
+        printf("========\n");
+
+    if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter)) {
+            printf("Couldn't create entry iterator\n");
+            return 1;
+    }
+    while (kSuccess == DTIterateEntries( entryIter, &dtEntry )) {
+        printf("=== Entry %p ===\n", dtEntry);
+
+        if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) {
+            printf("Couldn't create property iterator\n");
+            return 1;
+        }
+        while( kSuccess == DTIterateProperties( propIter, &name)) {
+            if(  kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
+                continue;
+            printf(" Property %s = %s\n", name, prop);
+        }
+        DTDisposePropertyIterator(propIter);
+        printf("========\n");
+    }
+    DTDisposeEntryIterator(entryIter);
+#endif
+
+    return 0;
+}
+
+#endif
+
diff --git a/i386/libsaio/device_tree.h b/i386/libsaio/device_tree.h
new file mode 100644
index 0000000..530cfaa
--- /dev/null
+++ b/i386/libsaio/device_tree.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc.  All Rights Reserved.
+ */
+
+#ifndef __DEVICE_TREE_H
+#define __DEVICE_TREE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct _Property {
+    char *             name;
+    uint32_t           length;
+    void *             value;
+
+    struct _Property * next;
+} Property;
+
+typedef struct _Node {
+    struct _Property * properties;
+    struct _Property * last_prop;
+    
+    struct _Node *     children;
+
+    struct _Node *     next;
+} Node;
+
+
+extern Property *
+DT__AddProperty(Node *node, char *name, uint32_t length, void *value);
+
+extern Node *
+DT__AddChild(Node *parent, char *name);
+
+Node *
+DT__FindNode(char *path, bool createIfMissing);
+
+extern void
+DT__FreeProperty(Property *prop);
+
+extern void
+DT__FreeNode(Node *node);
+
+extern char *
+DT__GetName(Node *node);
+
+void
+DT__Initialize(void);
+
+/*
+ * Free up memory used by in-memory representation
+ * of device tree.
+ */
+extern void
+DT__Finalize(void);
+
+void
+DT__FlattenDeviceTree(void **result, uint32_t *length);
+
+
+#endif /* __DEVICE_TREE_H */
diff --git a/i386/libsaio/disk.c b/i386/libsaio/disk.c
index aae0501..afb1057 100644
--- a/i386/libsaio/disk.c
+++ b/i386/libsaio/disk.c
@@ -44,10 +44,14 @@
  * All rights reserved.
  */
 
+#define UFS_SUPPORT 1
+
 #include "bootstruct.h"
 #include "libsaio.h"
 #include "fdisk.h"
+#if UFS_SUPPORT
 #include "ufs.h"
+#endif
 #include "hfs.h"
 #include "ntfs.h"
 #include "msdos.h"
@@ -101,6 +105,7 @@ static int getDriveInfo( int biosdev,  struct driveInfo *dip )
 	cc = get_drive_info(biosdev, &cached_di);
         if (cc < 0) {
 	    cached_di.valid = 0;
+            DEBUG_DISK(("get_drive_info returned error\n"));
 	    return (-1); // BIOS call error
 	}
     }
@@ -282,6 +287,7 @@ static int Biosread( int biosdev, unsigned int secno )
 //==========================================================================
 
 static int readBytes( int biosdev, unsigned int blkno,
+                      unsigned int byteoff,
                       unsigned int byteCount, void * buffer )
 {
 
@@ -292,7 +298,7 @@ static int readBytes( int biosdev, unsigned int blkno,
     DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__,
                 biosdev, blkno, byteCount, (unsigned)cbuf));
 
-    for ( ; byteCount; cbuf += BPS, blkno++ )
+    for ( ; byteCount; cbuf += copy_len, blkno++ )
     {
         error = Biosread( biosdev, blkno );
         if ( error )
@@ -301,9 +307,10 @@ static int readBytes( int biosdev, unsigned int blkno,
             return (-1);
         }
 
-        copy_len = (byteCount > BPS) ? BPS : byteCount;
-        bcopy( biosbuf, cbuf, copy_len );
+        copy_len = ((byteCount + byteoff) > BPS) ? (BPS - byteoff) : byteCount;
+        bcopy( biosbuf + byteoff, cbuf, copy_len );
         byteCount -= copy_len;
+        byteoff = 0;
     }
 
     DEBUG_DISK(("done\n"));
@@ -427,6 +434,7 @@ static BVRef newFDiskBVRef( int biosdev, int partno, unsigned int blkoff,
                             FSReadFile readFunc,
                             FSGetDirEntry getdirFunc,
                             FSGetFileBlock getBlockFunc,
+                            FSGetUUID getUUIDFunc,
                             BVGetDescription getDescriptionFunc,
                             int probe, int type )
 {
@@ -443,6 +451,7 @@ static BVRef newFDiskBVRef( int biosdev, int partno, unsigned int blkoff,
         bvr->fs_readfile    = readFunc;
         bvr->fs_getdirentry = getdirFunc;
         bvr->fs_getfileblock= getBlockFunc;
+        bvr->fs_getuuid     = getUUIDFunc;
         bvr->description    = getDescriptionFunc ?
             getDescriptionFunc : getVolumeDescription;
 	bvr->type           = type;
@@ -488,6 +497,7 @@ BVRef newAPMBVRef( int biosdev, int partno, unsigned int blkoff,
                    FSReadFile readFunc,
                    FSGetDirEntry getdirFunc,
                    FSGetFileBlock getBlockFunc,
+                   FSGetUUID getUUIDFunc,
                    BVGetDescription getDescriptionFunc,
                    int probe, int type )
 {
@@ -503,6 +513,7 @@ BVRef newAPMBVRef( int biosdev, int partno, unsigned int blkoff,
         bvr->fs_readfile    = readFunc;
         bvr->fs_getdirentry = getdirFunc;
         bvr->fs_getfileblock= getBlockFunc;
+        bvr->fs_getuuid     = getUUIDFunc;
         bvr->description    = getDescriptionFunc ?
             getDescriptionFunc : getVolumeDescription;
 	bvr->type           = type;
@@ -561,7 +572,9 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
     struct DiskBVMap *        map;
     int                       partno  = -1;
     BVRef                     bvr;
+#if UFS_SUPPORT
     BVRef                     booterUFS = NULL;
+#endif
     int                       spc;
     struct driveInfo          di;
     boot_drive_info_t         *dp;
@@ -599,6 +612,7 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
 
                 switch ( part->systid )
                 {
+#if UFS_SUPPORT
                     case FDISK_UFS:
                        bvr = newFDiskBVRef(
                                       biosdev, partno,
@@ -609,10 +623,12 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                                       UFSReadFile,
                                       UFSGetDirEntry,
                                       UFSGetFileBlock,
+                                      UFSGetUUID,
                                       UFSGetDescription,
                                       0,
 				      kBIOSDevTypeHardDrive);
                         break;
+#endif
 
                     case FDISK_HFS:
                         bvr = newFDiskBVRef(
@@ -624,11 +640,13 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                                       HFSReadFile,
                                       HFSGetDirEntry,
                                       HFSGetFileBlock,
+                                      HFSGetUUID,
                                       HFSGetDescription,
                                       0,
 				      kBIOSDevTypeHardDrive);
                         break;
 
+#if UFS_SUPPORT
                     case FDISK_BOOTER:
                         booterUFS = newFDiskBVRef(
                                       biosdev, partno,
@@ -639,17 +657,19 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                                       UFSReadFile,
                                       UFSGetDirEntry,
                                       UFSGetFileBlock,
+                                      UFSGetUUID,
                                       UFSGetDescription,
                                       0,
 				      kBIOSDevTypeHardDrive);
                         break;
+#endif
 
                    case FDISK_NTFS:
                         bvr = newFDiskBVRef(
                                       biosdev, partno,
                                       part->relsect,
                                       part,
-                                      0, 0, 0, 0, 0,
+                                      0, 0, 0, 0, 0, 0,
                                       NTFSGetDescription,
                                       0,
 				      kBIOSDevTypeHardDrive);
@@ -660,7 +680,7 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                                       biosdev, partno,
                                       part->relsect,
                                       part,
-                                      0, 0, 0, 0, 0, 0, 0,
+                                      0, 0, 0, 0, 0, 0, 0, 0,
 				      kBIOSDevTypeHardDrive);
                         break;
                 }
@@ -673,6 +693,7 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                 }
             }
 
+#if UFS_SUPPORT
             // Booting from a CD with an UFS filesystem embedded
             // in a booter partition.
 
@@ -685,6 +706,7 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                 }
                 else free( booterUFS );
             }
+#endif
         }
     } while (0);
 
@@ -707,6 +729,7 @@ static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr )
                             HFSReadFile,
 			    HFSGetDirEntry,
                             HFSGetFileBlock,
+                            HFSGetUUID,
 			    0,
 			    kBIOSDevTypeHardDrive);
 	bvr->next = map->bvr;
@@ -731,7 +754,7 @@ static BVRef diskScanAPMBootVolumes( int biosdev, int * countPtr )
     void *buffer = malloc(BPS);
 
     /* Check for alternate block size */
-    if (readBytes( biosdev, 0, BPS, buffer ) != 0) {
+    if (readBytes( biosdev, 0, 0, BPS, buffer ) != 0) {
         return NULL;
     }
     block0_p = buffer;
@@ -765,7 +788,7 @@ static BVRef diskScanAPMBootVolumes( int biosdev, int * countPtr )
             gDiskBVMap   = map;
 
             for (i=0; i<npart; i++) {
-                error = readBytes( biosdev, (kAPMSector + i) * factor, blksize, buffer );
+                error = readBytes( biosdev, (kAPMSector + i) * factor, 0, blksize, buffer );
 
                 if (error || OSSwapBigToHostInt16(dpme_p->dpme_signature) != DPME_SIGNATURE) {
                     break;
@@ -792,6 +815,7 @@ static BVRef diskScanAPMBootVolumes( int biosdev, int * countPtr )
                                       HFSReadFile,
                                       HFSGetDirEntry,
                                       HFSGetFileBlock,
+                                      HFSGetUUID,
                                       HFSGetDescription,
                                       0,
                                       kBIOSDevTypeHardDrive);
@@ -978,7 +1002,7 @@ int readBootSector( int biosdev, unsigned int secno, void * buffer )
         bootSector = gBootSector;
     }
 
-    error = readBytes( biosdev, secno, BPS, bootSector );
+    error = readBytes( biosdev, secno, 0, BPS, bootSector );
     if ( error || bootSector->signature != DISK_SIGNATURE )
         return -1;
 
@@ -991,6 +1015,7 @@ int readBootSector( int biosdev, unsigned int secno, void * buffer )
 void diskSeek( BVRef bvr, long long position )
 {
     bvr->fs_boff = position / BPS;
+    bvr->fs_byteoff = position % BPS;
 }
 
 //==========================================================================
@@ -1000,6 +1025,7 @@ int diskRead( BVRef bvr, long addr, long length )
 {
     return readBytes( bvr->biosdev,
                       bvr->fs_boff + bvr->part_boff,
+                      bvr->fs_byteoff,
                       length,
                       (void *) addr );
 }
@@ -1079,13 +1105,13 @@ int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len
     return 0;
 }
 
-void turnOffFloppy(void)
+
+int diskIsCDROM(BVRef bvr)
 {
-    /*
-     * Disable floppy:
-     * Hold controller in reset,
-     * disable DMA and IRQ,
-     * turn off floppy motors.
-     */
-    outb(0x3F2, 0x00);
+    struct driveInfo          di;
+
+    if (getDriveInfo(bvr->biosdev, &di) == 0 && di.no_emulation) {
+	return 1;
+    }
+    return 0;
 }
diff --git a/i386/libsaio/hfs.c b/i386/libsaio/hfs.c
index 5f1c48f..468843d 100644
--- a/i386/libsaio/hfs.c
+++ b/i386/libsaio/hfs.c
@@ -54,6 +54,7 @@ static HFSMasterDirectoryBlock *gHFSMDB;
 static char                    *gHFSPlusHeader;
 static HFSPlusVolumeHeader     *gHFSPlus;
 static char                    *gLinkTemp;
+static long long               gVolID;
 static char                    *gTempStr;
 
 #else  /* !__i386__ */
@@ -71,10 +72,11 @@ static HFSMasterDirectoryBlock *gHFSMDB =(HFSMasterDirectoryBlock*)gHFSMdbVib;
 static char                    gHFSPlusHeader[kBlockSize];
 static HFSPlusVolumeHeader     *gHFSPlus =(HFSPlusVolumeHeader*)gHFSPlusHeader;
 static char                    gLinkTemp[64];
+static long long               gVolID;
 
 #endif /* !__i386__ */
 
-static long ReadFile(void *file, long *length, void *base, long offset);
+static long ReadFile(void *file, unsigned long *length, void *base, long offset);
 static long GetCatalogEntryInfo(void *entry, long *flags, long *time,
                                 FinderInfo *finderInfo, long *infoValid);
 static long ResolvePathToCatalogEntry(char *filePath, long *flags,
@@ -102,7 +104,7 @@ static long CompareHFSPlusCatalogKeys(void *key, void *testKey);
 static long CompareHFSExtentsKeys(void *key, void *testKey);
 static long CompareHFSPlusExtentsKeys(void *key, void *testKey);
 
-extern long FastRelString(char *str1, char *str2);
+extern long FastRelString(u_int8_t *str1, u_int8_t *str2);
 extern long FastUnicodeCompare(u_int16_t *uniStr1, u_int32_t len1,
                 u_int16_t *uniStr2, u_int32_t len2);
 extern long BinaryUnicodeCompare(u_int16_t *uniStr1, u_int32_t len1,
@@ -166,6 +168,9 @@ long HFSInitPartition(CICell ih)
             CacheInit(ih, gCacheBlockSize);
             gCurrentIH = ih;
 
+            // grab the 64 bit volume ID
+            bcopy(&gHFSMDB->drFndrInfo[6], &gVolID, 8);
+
             // Get the Catalog BTree node size.
             extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
             extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
@@ -207,6 +212,9 @@ long HFSInitPartition(CICell ih)
     CacheInit(ih, gCacheBlockSize);
     gCurrentIH = ih;
 
+    // grab the 64 bit volume ID
+    bcopy(&gHFSPlus->finderInfo[24], &gVolID, 8);
+
     // Get the Catalog BTree node size.
     extent     = &gHFSPlus->catalogFile.extents;
     extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
@@ -386,10 +394,17 @@ HFSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock)
     return 0;
 }
 
+long HFSGetUUID(CICell ih, char *uuidStr)
+{
+    if (HFSInitPartition(ih) == -1) return -1;
+    if (gVolID == 0LL)  return -1;
+
+    return CreateUUIDString((uint8_t*)(&gVolID), sizeof(gVolID), uuidStr);
+}
 
 // Private Functions
 
-static long ReadFile(void * file, long * length, void * base, long offset)
+static long ReadFile(void * file, unsigned long * length, void * base, long offset)
 {
     void               *extents;
     long               fileID;
@@ -399,7 +414,7 @@ static long ReadFile(void * file, long * length, void * base, long offset)
 
     if (gIsHFSPlus) {
         fileID  = SWAP_BE32(hfsPlusFile->fileID);
-        fileLength = SWAP_BE64(hfsPlusFile->dataFork.logicalSize);
+        fileLength = (long)SWAP_BE64(hfsPlusFile->dataFork.logicalSize);
         extents = &hfsPlusFile->dataFork.extents;
     } else {
         fileID  = SWAP_BE32(hfsFile->fileID);
@@ -412,17 +427,14 @@ static long ReadFile(void * file, long * length, void * base, long offset)
         return -1;
     }
 
-    if (*length == 0 || (offset + *length) > fileLength) {
+    if ((*length == 0) || ((offset + *length) > fileLength)) {
         *length = fileLength - offset;
     }
 
-    // XXX
-#if 0
     if (*length > kLoadSize) {
         printf("File is too large.\n");
         return -1;
     }
-#endif
 
     *length = ReadExtent((char *)extents, fileLength, fileID,
                          offset, *length, (char *)base, 0);
@@ -496,7 +508,7 @@ static long ResolvePathToCatalogEntry(char * filePath, long * flags,
                                       void * entry, long dirID, long * dirIndex)
 {
     char                 *restPath;
-    long                 result, cnt, subFolderID, tmpDirIndex;
+    long                 result, cnt, subFolderID = 0, tmpDirIndex;
     HFSPlusCatalogFile   *hfsPlusFile;
 
     // Copy the file name to gTempStr
@@ -523,10 +535,11 @@ static long ResolvePathToCatalogEntry(char * filePath, long * flags,
             subFolderID = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->folderID);
         else
             subFolderID = SWAP_BE32(((HFSCatalogFolder *)entry)->folderID);
+    }
 
+    if ((*flags & kFileTypeMask) == kFileTypeDirectory)
         result = ResolvePathToCatalogEntry(restPath, flags, entry,
                                            subFolderID, dirIndex);
-    }
 
     if (gIsHFSPlus && ((*flags & kFileTypeMask) == kFileTypeFlat)) {
         hfsPlusFile = (HFSPlusCatalogFile *)entry;
@@ -577,10 +590,10 @@ static long GetCatalogEntry(long * dirIndex, char ** name,
     if (gIsHFSPlus) {
         utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode,
                       SWAP_BE16(((HFSPlusCatalogKey *)testKey)->nodeName.length),
-                      gTempStr, 256, OSBigEndian);
+                      (u_int8_t *)gTempStr, 256, OSBigEndian);
     } else {
         strncpy(gTempStr,
-                &((HFSCatalogKey *)testKey)->nodeName[1],
+                (const char *)&((HFSCatalogKey *)testKey)->nodeName[1],
                  ((HFSCatalogKey *)testKey)->nodeName[0]);
     }
     *name = gTempStr;
@@ -612,14 +625,14 @@ static long ReadCatalogEntry(char * fileName, long dirID,
         hfsPlusKey->parentID = SWAP_BE32(dirID);
         length = strlen(fileName);
         if (length > 255) length = 255;
-        utf_decodestr(fileName, hfsPlusKey->nodeName.unicode,
+        utf_decodestr((u_int8_t *)fileName, hfsPlusKey->nodeName.unicode,
                       &(hfsPlusKey->nodeName.length), 512, OSBigEndian);
     } else {
         hfsKey->parentID = SWAP_BE32(dirID);
         length = strlen(fileName);
         if (length > 31) length = 31;
         hfsKey->nodeName[0] = length;
-        strncpy(hfsKey->nodeName + 1, fileName, length);
+        strncpy((char *)(hfsKey->nodeName + 1), fileName, length);
     }
 
     return ReadBTreeEntry(kBTreeCatalog, &key, entry, dirIndex);
diff --git a/i386/libsaio/hfs.h b/i386/libsaio/hfs.h
index 765106e..eba6fd6 100644
--- a/i386/libsaio/hfs.h
+++ b/i386/libsaio/hfs.h
@@ -28,3 +28,4 @@ extern long HFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
                            FinderInfo * finderInfo, long * infoValid);
 extern void HFSGetDescription(CICell ih, char *str, long strMaxLen);
 extern long HFSGetFileBlock(CICell ih, char *str, unsigned long long *firstBlock);
+extern long HFSGetUUID(CICell ih, char *uuidStr);
diff --git a/i386/libsaio/hfs_compare.c b/i386/libsaio/hfs_compare.c
index 7a365f6..ec126a9 100644
--- a/i386/libsaio/hfs_compare.c
+++ b/i386/libsaio/hfs_compare.c
@@ -74,7 +74,7 @@ InitCompareTables(void)
 //
 //_______________________________________________________________________
 
-int32_t	FastRelString(char * str1, char * str2)
+int32_t	FastRelString(u_int8_t * str1, u_int8_t * str2)
 {
 	int32_t  bestGuess;
 	u_int8_t length, length2;
diff --git a/i386/libsaio/load.c b/i386/libsaio/load.c
index 77f9f8d..30e549d 100644
--- a/i386/libsaio/load.c
+++ b/i386/libsaio/load.c
@@ -86,7 +86,7 @@ long DecodeMachO(void *binary, entry_t *rentry, char **raddr, int *rsize)
   unsigned int vmend = 0;
   unsigned long  cnt;
   long  ret = -1;
-  unsigned int entry;
+  unsigned int entry = 0;
   
   gBinaryAddress = (unsigned long)binary;
   
diff --git a/i386/libsaio/md5c.c b/i386/libsaio/md5c.c
new file mode 100644
index 0000000..a78d0e5
--- /dev/null
+++ b/i386/libsaio/md5c.c
@@ -0,0 +1,344 @@
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ *
+ * $Id: md5c.c,v 1.1 2005/06/24 22:47:12 curtisg Exp $
+ *
+ * This code is the same as the code published by RSA Inc.  It has been
+ * edited for clarity and style only.
+ */
+
+#include <sys/types.h>
+
+#ifdef KERNEL
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+
+#include <sys/md5.h>
+
+
+#ifdef KERNEL
+#define memset(x,y,z)	bzero(x,z);
+#define memcpy(x,y,z)	bcopy(y, x, z)
+#endif
+
+#if defined(__i386__) || defined(__alpha__)
+#define Encode memcpy
+#define Decode memcpy
+#else /* __i386__ */
+
+/*
+ * Encodes input (u_int32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+
+/* XXX not prototyped, and not compatible with memcpy(). */
+static void
+Encode (output, input, len)
+	unsigned char *output;
+	u_int32_t *input;
+	unsigned int len;
+{
+	unsigned int i, j;
+
+	for (i = 0, j = 0; j < len; i++, j += 4) {
+		output[j] = (unsigned char)(input[i] & 0xff);
+		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+	}
+}
+
+/*
+ * Decodes input (unsigned char) into output (u_int32_t). Assumes len is
+ * a multiple of 4.
+ */
+
+static void
+Decode (output, input, len)
+	u_int32_t *output;
+	const unsigned char *input;
+	unsigned int len;
+{
+	unsigned int i, j;
+
+	for (i = 0, j = 0; j < len; i++, j += 4)
+		output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) |
+		    (((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24);
+}
+#endif /* i386 */
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions. */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/*
+ * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+	(a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define GG(a, b, c, d, x, s, ac) { \
+	(a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define HH(a, b, c, d, x, s, ac) { \
+	(a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define II(a, b, c, d, x, s, ac) { \
+	(a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+
+static void MD5Transform (u_int32_t state[4], const unsigned char block[64]);
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context. */
+
+void
+MD5Init (context)
+	MD5_CTX *context;
+{
+
+	context->count[0] = context->count[1] = 0;
+
+	/* Load magic initialization constants.  */
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xefcdab89;
+	context->state[2] = 0x98badcfe;
+	context->state[3] = 0x10325476;
+}
+
+/* 
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+
+void
+MD5Update (context, input, inputLen)
+	MD5_CTX *context;
+	const unsigned char *input;
+	unsigned int inputLen;
+{
+	unsigned int i, index, partLen;
+
+	/* Compute number of bytes mod 64 */
+	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+	/* Update number of bits */
+	if ((context->count[0] += ((u_int32_t)inputLen << 3))
+	    < ((u_int32_t)inputLen << 3))
+		context->count[1]++;
+	context->count[1] += ((u_int32_t)inputLen >> 29);
+
+	partLen = 64 - index;
+
+	/* Transform as many times as possible. */
+	if (inputLen >= partLen) {
+		memcpy((void *)&context->buffer[index], (const void *)input,
+		    partLen);
+		MD5Transform (context->state, context->buffer);
+
+		for (i = partLen; i + 63 < inputLen; i += 64)
+			MD5Transform (context->state, &input[i]);
+
+		index = 0;
+	}
+	else
+		i = 0;
+
+	/* Buffer remaining input */
+	memcpy ((void *)&context->buffer[index], (const void *)&input[i],
+	    inputLen-i);
+}
+
+/*
+ * MD5 padding. Adds padding followed by original length.
+ */
+
+void
+MD5Pad (context)
+	MD5_CTX *context;
+{
+	unsigned char bits[8];
+	unsigned int index, padLen;
+
+	/* Save number of bits */
+	Encode (bits, context->count, 8);
+
+	/* Pad out to 56 mod 64. */
+	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+	padLen = (index < 56) ? (56 - index) : (120 - index);
+	MD5Update (context, PADDING, padLen);
+
+	/* Append length (before padding) */
+	MD5Update (context, bits, 8);
+}
+
+/*
+ * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+
+void
+MD5Final (digest, context)
+	unsigned char digest[16];
+	MD5_CTX *context;
+{
+	/* Do padding. */
+	MD5Pad (context);
+
+	/* Store state in digest */
+	Encode (digest, context->state, 16);
+
+	/* Zeroize sensitive information. */
+	memset ((void *)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+
+static void
+MD5Transform (state, block)
+	u_int32_t state[4];
+	const unsigned char block[64];
+{
+	u_int32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+	Decode (x, block, 64);
+
+	/* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+	/* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+	/* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+	/* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+
+	/* Zeroize sensitive information. */
+	memset ((void *)x, 0, sizeof (x));
+}
diff --git a/i386/libsaio/memory.c b/i386/libsaio/memory.c
index a06026f..a7980eb 100644
--- a/i386/libsaio/memory.c
+++ b/i386/libsaio/memory.c
@@ -25,6 +25,7 @@
 #include "sl.h"
 #include "saio_internal.h"
 #include "bootstruct.h"
+#include "device_tree.h"
 
 static long  gImageLastKernelAddr;
 
@@ -32,6 +33,28 @@ static long  gImageLastKernelAddr;
 #define RoundPage(x)  ((((unsigned)(x)) + kPageSize - 1) & ~(kPageSize - 1))
 
 
+long
+AllocateMemoryRange(char * rangeName, long start, long length, long type)
+{
+    char *nameBuf;
+    uint32_t *buffer;
+    
+    nameBuf = malloc(strlen(rangeName) + 1);
+    if (nameBuf == 0) return -1;
+    strcpy(nameBuf, rangeName);
+    
+    buffer = malloc(2 * sizeof(uint32_t));
+    if (buffer == 0) return -1;
+    
+    buffer[0] = start;
+    buffer[1] = length;
+    
+    DT__AddProperty(gMemoryMapNode, nameBuf, 2 * sizeof(uint32_t), (char *)buffer);
+    
+    return 0;
+}
+
+#if 0
 long
 AllocateMemoryRange(char * rangeName, long start, long length, long type)
 {
@@ -50,6 +73,7 @@ AllocateMemoryRange(char * rangeName, long start, long length, long type)
     }
     return 0;
 }
+#endif
 
 long
 AllocateKernelMemory( long inSize )
diff --git a/i386/libsaio/misc.c b/i386/libsaio/misc.c
index 43d624a..64a6221 100644
--- a/i386/libsaio/misc.c
+++ b/i386/libsaio/misc.c
@@ -96,3 +96,47 @@ void enableA20()
     while (inb(PORT_B) & KB_INFULL);   /* wait until done */
 }
 
+static inline void
+do_cpuid(uint32_t selector, uint32_t *data)
+{
+	asm volatile ("cpuid"
+		: "=a" (data[0]),
+		  "=b" (data[1]),
+		  "=c" (data[2]),
+		  "=d" (data[3])
+		: "a"(selector));
+}
+
+
+//==========================================================================
+// Check to see that this is a supported hardware configuration.
+// If this hardware is supported, return 0.
+// If this hardware is not supported, return an error code.
+
+int
+checkForSupportedHardware()
+{
+    uint32_t cpuid_result[4];
+
+    do_cpuid(1, cpuid_result);
+    if ((cpuid_result[3] & 0x04000000) == 0) {
+        // Missing SSE2
+        return 2;
+    }
+    return 0;
+}
+
+#ifndef BOOT1
+
+//==========================================================================
+// Return the platform name for this hardware.
+//
+
+void
+getPlatformName(char *nameBuf)
+{
+    strcpy(nameBuf, "ACPI");
+}
+
+#endif
+
diff --git a/i386/libsaio/msdos.c b/i386/libsaio/msdos.c
index 1797d49..be9574c 100644
--- a/i386/libsaio/msdos.c
+++ b/i386/libsaio/msdos.c
@@ -129,7 +129,7 @@ MSDOSGetDescription(CICell ih, char *str, long strMaxLen)
     int 		rootDirSectors;
     int 		i, finished;
     char                *buf;
-    unsigned char	label[LABEL_LENGTH+1];
+    char	        label[LABEL_LENGTH+1];
 
     DLOG(0);
     buf = (char *)malloc(MAX_DOS_BLOCKSIZE);
@@ -197,7 +197,7 @@ MSDOSGetDescription(CICell ih, char *str, long strMaxLen)
         u_int8_t *rootDirBuffer;
         int j;
 
-        rootDirBuffer = (char *)malloc(MAX_DOS_BLOCKSIZE);
+        rootDirBuffer = (u_int8_t *)malloc(MAX_DOS_BLOCKSIZE);
     	
         DLOG(8);
         firstRootDirSecNum = OSSwapLittleToHostInt16(b33->bpbResSectors) +
@@ -216,7 +216,7 @@ MSDOSGetDescription(CICell ih, char *str, long strMaxLen)
                 else if (dirp->deAttributes == ATTR_WIN95)
                     continue;
                 else if (dirp->deAttributes & ATTR_VOLUME) {
-                    strncpy(label, dirp->deName, LABEL_LENGTH);
+                    strncpy(label, (char *)dirp->deName, LABEL_LENGTH);
                     finished = true;
                     break;
                 }
@@ -273,7 +273,7 @@ MSDOSGetDescription(CICell ih, char *str, long strMaxLen)
                     continue;
                 else if (dirp->deAttributes & ATTR_VOLUME) {
                     DLOG(0x31);
-                    strncpy(label, dirp->deName, LABEL_LENGTH);
+                    strncpy(label, (char *)dirp->deName, LABEL_LENGTH);
                     finished = true;
                     break;
                 }
@@ -310,10 +310,10 @@ MSDOSGetDescription(CICell ih, char *str, long strMaxLen)
     /* else look in the boot blocks */
     if (str[0] == '\0') {
         if (OSSwapLittleToHostInt16(b50->bpbRootDirEnts) == 0) { /* It's FAT32 */
-            strncpy(label, ((struct extboot *)bsp->bs710.bsExt)->exVolumeLabel, LABEL_LENGTH);
+            strncpy(label, (char *)((struct extboot *)bsp->bs710.bsExt)->exVolumeLabel, LABEL_LENGTH);
         }
         else if (((struct extboot *)bsp->bs50.bsExt)->exBootSignature == EXBOOTSIG) {
-            strncpy(label, ((struct extboot *)bsp->bs50.bsExt)->exVolumeLabel, LABEL_LENGTH);
+            strncpy(label, (char *)((struct extboot *)bsp->bs50.bsExt)->exVolumeLabel, LABEL_LENGTH);
         }
     }
 
diff --git a/i386/libsaio/nbp.c b/i386/libsaio/nbp.c
index a2b176c..552aa67 100644
--- a/i386/libsaio/nbp.c
+++ b/i386/libsaio/nbp.c
@@ -64,7 +64,7 @@ static long NBPLoadFile(CICell ih, char * filePath)
     nbpCommandTFTPReadFile_s  cmd;
 	UInt32                    ret;
 
-	strcpy(cmd.filename, filePath);
+	strcpy((char *)cmd.filename, filePath);
 	cmd.status     = nbpStatusFailed;
 	cmd.bufferSize = TFTP_LEN;
 	cmd.buffer     = TFTP_ADDR;
diff --git a/i386/libsaio/ntfs.c b/i386/libsaio/ntfs.c
index b3fbbc7..d4226f2 100644
--- a/i386/libsaio/ntfs.c
+++ b/i386/libsaio/ntfs.c
@@ -92,7 +92,7 @@ ntfs_fixup(
 			return (ERROR);
 		}
 		*cfxp = *fxp;
-		((caddr_t) cfxp) += bytesPerSector;
+                cfxp = (u_int16_t *)(((caddr_t)cfxp) + bytesPerSector);
 	}
 	return (0);
 }
@@ -141,7 +141,7 @@ ntfs_find_attr(
 }
 
 static int
-memcmp(char *p1, char *p2, int len)
+memcmp(const char *p1, const char *p2, int len)
 {
     while (len--) {
         if (*p1++ != *p2++)
@@ -199,7 +199,7 @@ NTFSGetDescription(CICell ih, char *str, long strMaxLen)
     /*
      * Check the "NTFS    " signature.
      */
-    if (memcmp(boot->bf_sysid, "NTFS    ", 8) != 0)
+    if (memcmp((const char *)boot->bf_sysid, "NTFS    ", 8) != 0)
     {
         goto error;
     }
@@ -295,7 +295,7 @@ NTFSGetDescription(CICell ih, char *str, long strMaxLen)
     
     str[0] = '\0';
 
-    utf_encodestr( nameAttr, nameSize / 2, str, strMaxLen, OSLittleEndian );
+    utf_encodestr( nameAttr, nameSize / 2, (u_int8_t *)str, strMaxLen, OSLittleEndian );
 
     free(buf);
     return;
diff --git a/i386/libsaio/saio_internal.h b/i386/libsaio/saio_internal.h
index a0d2d77..4923263 100644
--- a/i386/libsaio/saio_internal.h
+++ b/i386/libsaio/saio_internal.h
@@ -76,6 +76,7 @@ extern void   sleep(int n);
 extern void   initKernBootStruct(int biosdev);
 extern void   reserveKernBootStruct(void);
 extern void   copyKernBootStruct(void);
+extern void   finalizeBootStruct(void);
 
 /* cache.c */
 extern void   CacheInit(CICell ih, long blockSize);
@@ -90,12 +91,13 @@ extern int    getchar(void);
 extern int    printf(const char *format, ...);
 extern int    error(const char *format, ...);
 extern int    verbose(const char *format, ...);
-extern void   stop(const char *message);
+extern void   stop(const char *format, ...);
 
 /* disk.c */
 extern BVRef  diskScanBootVolumes(int biosdev, int *count);
 extern void   diskSeek(BVRef bvr, long long position);
 extern int    diskRead(BVRef bvr, long addr, long length);
+extern int    diskIsCDROM(BVRef bvr);
 extern int    rawDiskRead(BVRef bvr, unsigned int secno, void *buffer, unsigned int len);
 extern int    rawDiskWrite(BVRef bvr, unsigned int secno, void *buffer, unsigned int len);
 extern int    readBootSector(int biosdev, unsigned int secno, void *buffer);
@@ -118,6 +120,8 @@ long AllocateMemoryRange(char * rangeName, long start, long length, long type);
 
 /* misc.c */
 extern void   enableA20(void);
+extern int    checkForSupportedHardware();
+extern void   getPlatformName(char *nameBuf);
 
 /* nbp.c */
 extern UInt32 nbpUnloadBaseCode();
@@ -126,7 +130,7 @@ extern BVRef  nbpScanBootVolumes(int biosdev, int *count);
 /* stringTable.c */
 extern char * newStringFromList(char **list, int *size);
 extern int    stringLength(const char *table, int compress);
-extern BOOL   getValueForStringTableKey(const char *table, const char *key, const char **val, int *size);
+extern BOOL   getValueForConfigTableKey(const char *table, const char *key, const char **val, int *size);
 extern BOOL   removeKeyFromTable(const char *key, char *table);
 extern char * newStringForStringTableKey(char *table, char *key);
 extern char * newStringForKey(char *key);
@@ -149,6 +153,8 @@ extern long   GetDirEntry(const char *dirSpec, long *dirIndex, const char **name
 extern long   GetFileInfo(const char *dirSpec, const char *name,
                           long *flags, long *time);
 extern long   GetFileBlock(const char *fileSpec, unsigned long long *firstBlock);
+extern long   GetFSUUID(char *spec, char *uuidStr);
+extern long   CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr);
 extern int    openmem(char *buf, int len);
 extern int    open(const char *str, int how);
 extern int    close(int fdesc);
diff --git a/i386/libsaio/saio_types.h b/i386/libsaio/saio_types.h
index e7b6338..0d03099 100644
--- a/i386/libsaio/saio_types.h
+++ b/i386/libsaio/saio_types.h
@@ -57,6 +57,52 @@ struct driveParameters {
     int totalDrives;
 };
 
+
+/*
+ * BIOS drive information.
+ */
+struct boot_drive_info {
+    struct drive_params {
+	unsigned short buf_size;
+	unsigned short info_flags;
+	unsigned long  phys_cyls;
+	unsigned long  phys_heads;
+	unsigned long  phys_spt;
+	unsigned long long phys_sectors;
+	unsigned short phys_nbps;
+	unsigned short dpte_offset;
+	unsigned short dpte_segment;
+	unsigned short key;
+	unsigned char  path_len;
+	unsigned char  reserved1;
+	unsigned short reserved2;
+	unsigned char  bus_type[4];
+	unsigned char  interface_type[8];
+	unsigned char  interface_path[8];
+	unsigned char  dev_path[8];
+	unsigned char  reserved3;
+	unsigned char  checksum;
+    } params __attribute__((packed));
+    struct drive_dpte {
+	unsigned short io_port_base;
+	unsigned short control_port_base;
+	unsigned char  head_flags;
+	unsigned char  vendor_info;
+	unsigned char  irq         : 4;
+	unsigned char  irq_unused  : 4;
+	unsigned char  block_count;
+	unsigned char  dma_channel : 4;
+	unsigned char  dma_type    : 4;
+	unsigned char  pio_type    : 4;
+	unsigned char  pio_unused  : 4;
+	unsigned short option_flags;
+	unsigned short reserved;
+	unsigned char  revision;
+	unsigned char  checksum;
+    } dpte __attribute__((packed));
+} __attribute__((packed));
+typedef struct boot_drive_info boot_drive_info_t;
+
 struct driveInfo {
     boot_drive_info_t di;
     int uses_ebios;
@@ -80,6 +126,7 @@ typedef long (*FSGetFileBlock)(CICell ih, char *filePath, unsigned long long *fi
 typedef long (*FSGetDirEntry)(CICell ih, char * dirPath, long * dirIndex,
                               char ** name, long * flags, long * time,
                               FinderInfo * finderInfo, long * infoValid);
+typedef long (* FSGetUUID)(CICell ih, char *uuidStr);
 typedef void (*BVGetDescription)(CICell ih, char * str, long strMaxLen);
 
 struct iob {
@@ -115,10 +162,12 @@ struct BootVolume {
     unsigned int     part_boff;       /* partition block offset */
     unsigned int     part_type;       /* partition type */
     unsigned int     fs_boff;         /* 1st block # of next read */
+    unsigned int     fs_byteoff;      /* Byte offset for read within block */
     FSLoadFile       fs_loadfile;     /* FSLoadFile function */
     FSReadFile       fs_readfile;     /* FSReadFile function */
     FSGetDirEntry    fs_getdirentry;  /* FSGetDirEntry function */
     FSGetFileBlock   fs_getfileblock; /* FSGetFileBlock function */
+    FSGetUUID        fs_getuuid;      /* FSGetUUID function */
     unsigned int     bps;             /* bytes per sector for this device */
     char             name[BVSTRLEN];  /* (name of partition) */
     char             type_name[BVSTRLEN]; /* (type of partition, eg. Apple_HFS) */
@@ -140,6 +189,7 @@ enum {
     kBIOSDevMask          = 0xFF
 };
 
+
 //#define BIOS_DEV_TYPE(d)  ((d) & kBIOSDevTypeMask)
 #define BIOS_DEV_UNIT(bvr)  ((bvr)->biosdev - (bvr)->type)
 
@@ -168,4 +218,9 @@ enum {
     kBlockDeviceType   = kBIOSDevTypeHardDrive
 } gBootFileType_t;
 
+enum {
+    kCursorTypeHidden    = 0x0100,
+    kCursorTypeUnderline = 0x0607
+};
+
 #endif /* !__LIBSAIO_SAIO_TYPES_H */
diff --git a/i386/libsaio/stringTable.c b/i386/libsaio/stringTable.c
index 65ef09e..b726688 100644
--- a/i386/libsaio/stringTable.c
+++ b/i386/libsaio/stringTable.c
@@ -404,11 +404,18 @@ BOOL getIntForKey(
 {
     const char *val;
     int size, sum;
+    BOOL negative = NO;
     
     if (getValueForKey(key, &val, &size)) {
+        if (*val == '-') {
+            negative = YES;
+            val++;
+        }
 	for (sum = 0; size > 0; size--) {
+            if (*val < '0' || *val > '9') return NO;
 	    sum = (sum * 10) + (*val++ - '0');
 	}
+        if (negative) sum = -sum;
 	*value = sum;
 	return YES;
     }
@@ -421,9 +428,9 @@ BOOL getValueForKey(
     int *size
 )
 {
-    if (getValueForBootKey(bootArgs->bootString, key, val, size))
+    if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
 	return YES;
-    else if (getValueForConfigTableKey(bootArgs->config, key, val, size))
+    else if (getValueForConfigTableKey(bootInfo->config, key, val, size))
 	return YES;
 
     return NO;
@@ -443,13 +450,13 @@ int sysConfigValid;
 int
 loadConfigFile(const char *configFile)
 {
-    char *configPtr = bootArgs->config;
+    char *configPtr = bootInfo->config;
     int fd, count;
     
     /* Read config file into memory */
     if ((fd = open(configFile, 0)) >= 0)
     {
-        if ((configPtr - bootArgs->config) > CONFIG_SIZE) {
+        if ((configPtr - bootInfo->config) > CONFIG_SIZE) {
             error("No room in memory for config files\n");
             close(fd);
             return -1;
@@ -463,7 +470,7 @@ loadConfigFile(const char *configFile)
 	*configPtr++ = 0;
 	*configPtr = 0;
 
-        bootArgs->configEnd = configPtr;
+        bootInfo->configEnd = configPtr;
 
 	return 0;
     } else {
@@ -484,7 +491,7 @@ loadConfigFile(const char *configFile)
 void
 printSystemConfig(void)
 {
-    char *p1 = bootArgs->config;
+    char *p1 = bootInfo->config;
     char *p2 = p1, tmp;
 
     while (*p1 != '\0') {
@@ -602,7 +609,7 @@ loadSystemConfig(
 	sysConfigValid = 1;
         // Check for XML file;
         // if not XML, gConfigDict will remain 0.
-        ParseXMLFile(bootArgs->config, &gConfigDict);
+        ParseXMLFile(bootInfo->config, &gConfigDict);
     }
     free(buf);
     return (ret < 0 ? ret : doDefault);
diff --git a/i386/libsaio/sys.c b/i386/libsaio/sys.c
index 01b6f15..1fa09cd 100644
--- a/i386/libsaio/sys.c
+++ b/i386/libsaio/sys.c
@@ -56,7 +56,9 @@
 
 #include "libsaio.h"
 #include "bootstruct.h"
-
+#include <sys/md5.h>
+#include <uuid/uuid.h>
+#include <Kernel/uuid/namespace.h>
 
 struct devsw {
     const char *  name;
@@ -144,7 +146,7 @@ long LoadThinFatFile(const char *fileSpec, void **binary)
     const char       *filePath;
     FSReadFile readFile;
     BVRef      bvr;
-    long       length, length2;
+    unsigned long    length, length2;
   
     // Resolve the boot volume from the file spec.
 
@@ -186,6 +188,73 @@ long LoadThinFatFile(const char *fileSpec, void **binary)
     return length;
 }
 
+long GetFSUUID(char *spec, char *uuidStr)
+{
+    BVRef      bvr;
+    long       rval = -1;
+    const char *devSpec;
+
+    if ((bvr = getBootVolumeRef(spec, &devSpec)) == NULL)
+        return -1;
+
+    if(bvr->fs_getuuid)
+        rval = bvr->fs_getuuid(bvr, uuidStr);
+
+    return rval;
+}
+
+
+// filesystem-specific getUUID functions call this shared string generator
+long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr)
+{
+    unsigned  fmtbase, fmtidx, i;
+    uint8_t   uuidfmt[] = { 4, 2, 2, 2, 6 };
+    char     *p = uuidStr;
+    MD5_CTX   md5c;
+    uint8_t   mdresult[16];
+
+    bzero(mdresult, sizeof(mdresult));
+
+    // just like AppleFileSystemDriver
+    MD5Init(&md5c);
+    MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1));
+    MD5Update(&md5c, uubytes, nbytes);
+    MD5Final(mdresult, &md5c);
+
+    // this UUID has been made version 3 style (i.e. via namespace)
+    // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte)
+    mdresult[6] = 0x30 | ( mdresult[6] & 0x0F );
+    mdresult[8] = 0x80 | ( mdresult[8] & 0x3F );
+
+
+    // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292
+    i = 0; fmtbase = 0;
+    for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) {
+        for(i=0; i < uuidfmt[fmtidx]; i++) {
+            uint8_t byte = mdresult[fmtbase+i];
+            char nib;
+
+            nib = byte >> 4;
+            *p = nib + '0';  // 0x4 -> '4'
+            if(*p > '9')  *p = (nib - 9 + ('A'-1));  // 0xB -> 'B'
+            p++;
+
+            nib = byte & 0xf;
+            *p = nib + '0';  // 0x4 -> '4'
+            if(*p > '9')  *p = (nib - 9 + ('A'-1));  // 0xB -> 'B'
+            p++;
+
+        }
+        fmtbase += i;
+        if(fmtidx < sizeof(uuidfmt)-1)
+            *(p++) = '-';
+        else
+            *p = '\0';
+    }
+
+    return 0;
+}
+
 
 //==========================================================================
 // GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION.
@@ -543,14 +612,15 @@ int readdir_ext(struct dirstuff * dirp, const char ** name, long * flags,
 
 int currentdev()
 {
-    return bootArgs->kernDev;
+    printf("currentdev = %d\n", bootInfo->kernDev);
+    return bootInfo->kernDev;
 }
 
 //==========================================================================
 
 int switchdev(int dev)
 {
-    bootArgs->kernDev = dev;
+    bootInfo->kernDev = dev;
     return dev;
 }
 
@@ -620,9 +690,9 @@ BVRef getBootVolumeRef( const char * path, const char ** outPath )
 {
     const char * cp;
     BVRef        bvr;
-    int          type = B_TYPE( bootArgs->kernDev );
-    int          unit = B_UNIT( bootArgs->kernDev );
-    int          part = B_PARTITION( bootArgs->kernDev );
+    int          type = B_TYPE( bootInfo->kernDev );
+    int          unit = B_UNIT( bootInfo->kernDev );
+    int          part = B_PARTITION( bootInfo->kernDev );
     int          biosdev = gBIOSDev;
     static BVRef lastBVR = 0;
     static int   lastKernDev;
@@ -636,7 +706,7 @@ BVRef getBootVolumeRef( const char * path, const char ** outPath )
     if (*cp != LP)  // no left paren found
     {
         cp = path;
-        if ( lastBVR && lastKernDev == bootArgs->kernDev )
+        if ( lastBVR && lastKernDev == bootInfo->kernDev )
         {
             bvr = lastBVR;
             goto quick_exit;
@@ -703,10 +773,10 @@ BVRef getBootVolumeRef( const char * path, const char ** outPath )
     // Record the most recent device parameters in the
     // KernBootStruct.
 
-    bootArgs->kernDev = biosdev;
+    bootInfo->kernDev = biosdev;
 
     lastBVR = bvr;
-    lastKernDev = bootArgs->kernDev;
+    lastKernDev = bootInfo->kernDev;
 
 quick_exit:
     // Returns the file path following the device spec.
diff --git a/i386/libsaio/ufs.c b/i386/libsaio/ufs.c
index 797eb4c..ec8c060 100644
--- a/i386/libsaio/ufs.c
+++ b/i386/libsaio/ufs.c
@@ -32,6 +32,10 @@
 #include "ufs.h"
 #include "ufs_byteorder.h"
 
+#if !defined(MAXNAMLEN) && defined(UFSMAXNAMLEN)
+#define MAXNAMLEN UFSMAXNAMLEN
+#endif
+
 typedef struct dinode Inode, *InodePtr;
 
 // Private function prototypes
@@ -47,7 +51,7 @@ static long FindFileInDir(char *fileName, long *flags,
                           InodePtr fileInode, InodePtr dirInode);
 static char *ReadFileBlock(InodePtr fileInode, long fragNum, long blockOffset,
                            long length, char *buffer, long cache);
-static long ReadFile(InodePtr fileInode, long *length, void *base, long offset);
+static long ReadFile(InodePtr fileInode, unsigned long *length, void *base, long offset);
 
 #define kDevBlockSize (0x200)    // Size of each disk block.
 #define kDiskLabelBlock (15)     // Block the DL is in.
@@ -59,6 +63,9 @@ static long long gPartitionBase;
 static char      *gULBuf;
 static char      *gFSBuf;
 static struct fs *gFS;
+#if !BOOT1
+static struct ufslabel  gUFSLabel;   // for UUID
+#endif
 static long      gBlockSize;
 static long      gFragSize;
 static long      gFragsPerBlock;
@@ -75,6 +82,9 @@ static long long gPartitionBase;
 static char      gDLBuf[8192];
 static char      gFSBuf[SBSIZE];
 static struct fs *gFS;
+#if !BOOT1
+static struct ufslabel  gUFSLabel;   // for UUID
+#endif
 static long      gBlockSize;
 static long      gFragSize;
 static long      gFragsPerBlock;
@@ -92,6 +102,10 @@ static InodePtr  gFileInodePtr = &_gFileInode;
 
 long UFSInitPartition( CICell ih )
 {
+#if !BOOT1
+    long ret;
+#endif
+
     if (ih == gCurrentIH) {
 #ifdef __i386__
         CacheInit(ih, gBlockSize);
@@ -119,6 +133,16 @@ long UFSInitPartition( CICell ih )
     // Assume there is no Disk Label
     gPartitionBase = 0;
 
+#if !BOOT1
+    // read the disk label to get the UUID
+    // (rumor has it that UFS headers can be either-endian on disk; hopefully
+    // that isn't true for this UUID field).
+    Seek(ih, gPartitionBase + UFS_LABEL_OFFSET);
+    ret = Read(ih, (long)&gUFSLabel, UFS_LABEL_SIZE);
+    if(ret != 0)
+        bzero(&gUFSLabel, UFS_LABEL_SIZE);
+#endif /* !BOOT1 */
+
     // Look for the Super Block
     Seek(ih, gPartitionBase + SBOFF);
     Read(ih, (long)gFSBuf, SBSIZE);
@@ -146,6 +170,20 @@ long UFSInitPartition( CICell ih )
     return 0;
 }
 
+#if !BOOT1
+
+long UFSGetUUID(CICell ih, char *uuidStr)
+{
+  long long uuid = gUFSLabel.ul_uuid;
+
+  if (UFSInitPartition(ih) == -1) return -1;
+  if (uuid == 0LL)  return -1;
+
+  return CreateUUIDString((uint8_t*)(&uuid), sizeof(uuid), uuidStr);
+}
+
+#endif /* !BOOT1 */
+
 long UFSLoadFile( CICell ih, char * filePath )
 {
     return UFSReadFile(ih, filePath, (void *)gFSLoadAddress, 0, 0);
@@ -224,7 +262,7 @@ UFSGetDescription(CICell ih, char *str, long strMaxLen)
         if (*p != magic_bytes[i])
             return;
     }
-    strncpy(str, ul->ul_name, strMaxLen);
+    strncpy(str, (const char *)ul->ul_name, strMaxLen);
 }
 
 long
@@ -443,7 +481,7 @@ static char * ReadFileBlock( InodePtr fileInode, long fragNum, long blockOffset,
     return buffer;
 }
 
-static long ReadFile( InodePtr fileInode, long * length, void * base, long offset )
+static long ReadFile( InodePtr fileInode, unsigned long * length, void * base, long offset )
 {
     long bytesLeft, curSize, curFrag;
     char *buffer, *curAddr = (char *)base;
@@ -471,7 +509,7 @@ static long ReadFile( InodePtr fileInode, long * length, void * base, long offse
     while (bytesLeft) {
         curSize = gBlockSize;
         if (curSize > bytesLeft) curSize = bytesLeft;
-        if (offset != 0) curSize -= offset;
+        if ((offset + curSize) > gBlockSize) curSize = (gBlockSize - offset);
 
         buffer = ReadFileBlock(fileInode, curFrag, offset, curSize, curAddr, 0);
         if (buffer == 0) break;
diff --git a/i386/libsaio/ufs.h b/i386/libsaio/ufs.h
index 9d7743d..5de2365 100644
--- a/i386/libsaio/ufs.h
+++ b/i386/libsaio/ufs.h
@@ -28,4 +28,5 @@ extern long UFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
                            FinderInfo * finderInfo, long * infoValid);
 extern void UFSGetDescription(CICell ih, char *str, long strMaxLen);
 extern long UFSGetFileBlock(CICell ih, char *str, unsigned long long *firstBlock);
+extern long UFSGetUUID(CICell ih, char *uuidStr);
 
diff --git a/i386/libsaio/ufs_byteorder.c b/i386/libsaio/ufs_byteorder.c
index 838f107..a1c3f71 100644
--- a/i386/libsaio/ufs_byteorder.c
+++ b/i386/libsaio/ufs_byteorder.c
@@ -52,7 +52,7 @@ byte_swap_longlongs(unsigned long long *array, int count)
 #endif
 
 void
-byte_swap_ints(int *array, int count)
+byte_swap_ints(unsigned int *array, int count)
 {
 	register int	i;
 
@@ -61,7 +61,7 @@ byte_swap_ints(int *array, int count)
 }
 
 void
-byte_swap_shorts(short *array, int count)
+byte_swap_shorts(unsigned short *array, int count)
 {
 	register int	i;
 
@@ -71,7 +71,7 @@ byte_swap_shorts(short *array, int count)
 
 #if UNUSED
 static void
-swapBigIntsToHost(int *array, int count)
+swapBigIntsToHost(unsigned int *array, int count)
 {
 	register int	i;
 
@@ -80,7 +80,7 @@ swapBigIntsToHost(int *array, int count)
 }
 
 static void
-swapBigShortToHosts(short *array, int count)
+swapBigShortToHosts(unsigned short *array, int count)
 {
 	register int	i;
 
@@ -95,16 +95,16 @@ byte_swap_superblock(struct fs *sb)
 	u_int16_t *   usptr;
 	unsigned long size;
 
-	byte_swap_ints(((int32_t *)&sb->fs_firstfield), 52);
+	byte_swap_ints(((u_int32_t *)&sb->fs_firstfield), 52);
 	byte_swap_int(sb->fs_cgrotor);
 	byte_swap_int(sb->fs_cpc);
-	byte_swap_shorts((int16_t *)sb->fs_opostbl, 16 * 8); 
-	byte_swap_ints((int32_t *)sb->fs_sparecon, 50);
-	byte_swap_ints((int32_t *)&sb->fs_contigsumsize, 3);
+	byte_swap_shorts((u_int16_t *)sb->fs_opostbl, 16 * 8); 
+	byte_swap_ints((u_int32_t *)sb->fs_sparecon, 50);
+	byte_swap_ints((u_int32_t *)&sb->fs_contigsumsize, 3);
 #if UNUSED
 	byte_swap_longlongs((u_int64_t *)&sb->fs_maxfilesize,3);
 #endif
-	byte_swap_ints((int32_t *)&sb->fs_state, 6);
+	byte_swap_ints((u_int32_t *)&sb->fs_state, 6);
 
 	/* Got these magic numbers from mkfs.c in newfs */
 	if (sb->fs_nrpos != 8 || sb->fs_cpc > 16) {
diff --git a/i386/libsaio/ufs_byteorder.h b/i386/libsaio/ufs_byteorder.h
index dde46e4..f4861a2 100644
--- a/i386/libsaio/ufs_byteorder.h
+++ b/i386/libsaio/ufs_byteorder.h
@@ -44,12 +44,11 @@
 #include <ufs/ufs/dir.h>
 #include <ufs/ffs/fs.h>
 
-void byte_swap_ints(int *array, int count);
-void byte_swap_shorts(short *array, int count);
+void byte_swap_ints(unsigned int *array, int count);
+void byte_swap_shorts(unsigned short *array, int count);
 void byte_swap_longlongs(unsigned long long *array, int count);
 
 void byte_swap_superblock(struct fs *sb);
-void byte_swap_partition(struct partition *part);
 void byte_swap_dinode_in(struct dinode *di);
 void byte_swap_dir_block_in(char *addr, int count);
 void byte_swap_inode_in(struct dinode *dc, struct dinode *ic);
diff --git a/i386/libsaio/vbe.h b/i386/libsaio/vbe.h
index 295b889..1c59af5 100644
--- a/i386/libsaio/vbe.h
+++ b/i386/libsaio/vbe.h
@@ -242,7 +242,7 @@ typedef struct {
     unsigned char   Reserved[40];
 } VBECRTCInfoBlock;
 
-#pragma options align=reset
+#pragma pack()
 
 /*
  * Defined flags for 'Flags' field in VBECRTCInfoBlock.
diff --git a/i386/nasm/Makefile b/i386/nasm/Makefile
index 570169f..5dc06e4 100644
--- a/i386/nasm/Makefile
+++ b/i386/nasm/Makefile
@@ -10,7 +10,7 @@ MANINSTALLDIR = $(SYMROOT)
 INSTALLDIR = $(SYMROOT)
 
 OPTIM = -O2
-CFLAGS	= $(OPTIM) -g  -Wmost -Werror
+CFLAGS	= $(OPTIM) -g  -Wmost -Werror -fno-builtin
 DEFINES=
 INC = -I.
 ifneq "" "$(wildcard /bin/mkdirs)"
diff --git a/i386/rcz/Makefile b/i386/rcz/Makefile
index 58b517b..5fdf893 100644
--- a/i386/rcz/Makefile
+++ b/i386/rcz/Makefile
@@ -6,7 +6,7 @@ UTILDIR = ../util
 LIBSADIR = ../libsa
 INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone
 
-OPTIM = -Os
+OPTIM = -Os -Oz
 CFLAGS	= $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
           -fno-builtin -static
 DEFINES=
diff --git a/i386/strings/BootHelp.txt b/i386/strings/BootHelp.txt
index e76bfda..9db0982 100644
--- a/i386/strings/BootHelp.txt
+++ b/i386/strings/BootHelp.txt
@@ -7,8 +7,8 @@ Example arguments include
  device: rd=<BSD device name>       (e.g. rd=disk0s2)
          rd=*<IODeviceTree path>    (e.g. rd=*/PCI0@0/CHN0@0/@0:1)
  kernel: kernel name                (e.g. "mach_kernel" - must be in "/" )
- flags: -v (verbose)  -s (single user), 
-        -f (safe)     -F (ignore boot file)
+ flags: -v (verbose)    -s (single user mode), 
+        -x (safe mode)  -F (ignore boot configuration file)
  "Graphics Mode"="WIDTHxHEIGHTxDEPTH" (e.g. "1024x768x32")
     For VESA 3.0 graphics, you may append a refresh rate
     after an "@" character (e.g. "1280x1024x32@75")
@@ -18,7 +18,7 @@ Example arguments include
 Example: mach_kernel rd=disk0s1 -v "Graphics Mode"="4096x4096x32@85"
 
 If the computer won't start up properly, you may be able to start it up using
-safe mode.  Type -f to start up in safe mode, which ignores all cached
+safe mode.  Type -x to start up in safe mode, which ignores all cached
 driver files.
 
 Special booter commands:
diff --git a/i386/strings/Makefile b/i386/strings/Makefile
index cb04324..42c01fe 100644
--- a/i386/strings/Makefile
+++ b/i386/strings/Makefile
@@ -13,7 +13,7 @@ all:
 
 install_i386:: $(INSTALLDIR)
 	cp $(FILES) $(INSTALLDIR)
-	chown -fR root.wheel $(INSTALLDIR)
+	chown -fR root:wheel $(INSTALLDIR)
 	chmod -R ugo-w  $(INSTALLDIR)
 
 include ../MakeInc.dir
diff --git a/i386/testmodule/Makefile b/i386/testmodule/Makefile
index 3baf106..fce5e07 100644
--- a/i386/testmodule/Makefile
+++ b/i386/testmodule/Makefile
@@ -6,7 +6,7 @@ DIR = testmodule
 include ../MakePaths.dir
 
 DEBUG = -g
-OPTIM = -Os
+OPTIM = -Os -Oz
 CFLAGS	= $(DEBUG) $(OPTIM) $(MORECPP) -arch i386 -Wmost -DTEST_INTERNAL_USER
 DEFINES=
 CONFIG = hd
diff --git a/i386/util/Makefile b/i386/util/Makefile
index 1fd68e5..2dfda04 100644
--- a/i386/util/Makefile
+++ b/i386/util/Makefile
@@ -12,7 +12,7 @@ VPATH = $(OBJROOT):$(SYMROOT)
 INSTALLDIR = $(DSTROOT)/usr/standalone/i386
 LOCALBIN = $(DSTROOT)/usr/local/bin
 
-OPTIM = -Os
+OPTIM = -Os -Oz
 CFLAGS = $(RC_CFLAGS) $(OPTIM) -Wmost -Werror -g
 LDFLAGS =
 CFILES = machOconv.c
-- 
2.45.2