All pastes #1314651 Raw Edit

Stuff

public text v1 · immutable
#1314651 ·published 2009-01-21 13:32 UTC
rendered paste body
diff -Naur v51_src/i386/boot0/Makefile boot-132_dfe_r146/i386/boot0/Makefile
--- v51_src/i386/boot0/Makefile	2008-10-02 03:46:06.000000000 +0200
+++ boot-132_dfe_r146/i386/boot0/Makefile	2007-06-27 17:51:09.000000000 +0200
@@ -2,17 +2,16 @@
 DIR = boot0
 include ../MakePaths.dir
 
-#NASM = $(SYMROOT)/nasm
-NASM = nasm
+NASM = $(SYMROOT)/nasm
 INSTALLDIR = $(DSTROOT)/usr/standalone/i386
 DIRS_NEEDED = $(SYMROOT)
 
 all: $(DIRS_NEEDED) boot0 chain0
 
-boot0: boot0.s Makefile
+boot0: boot0.s Makefile $(NASM)
 	$(NASM) boot0.s -o $(SYMROOT)/$@
 
-chain0: chain0.s Makefile
+chain0: chain0.s Makefile $(NASM)
 	$(NASM) chain0.s -o $(SYMROOT)/$@
 
 install_i386:: all $(INSTALLDIR)
diff -Naur v51_src/i386/boot0/boot0.s boot-132_dfe_r146/i386/boot0/boot0.s
--- v51_src/i386/boot0/boot0.s	2008-10-02 03:46:06.000000000 +0200
+++ boot-132_dfe_r146/i386/boot0/boot0.s	2007-06-27 17:51:09.000000000 +0200
@@ -39,11 +39,6 @@
 ; This code is written for the NASM assembler.
 ;   nasm boot0.s -o boot0
 
-;
-; This version of boot0 implements hybrid GUID/MBR partition scheme support
-;
-; Written by Tams Kosrszky on 2008-03-10
-;
 
 ;
 ; Set to 1 to enable obscure debug messages.
@@ -51,9 +46,12 @@
 DEBUG                EQU  0
 
 ;
-; Set to 1 to enable verbose mode
+; Set to 1 to support loading the partition booter (boot1) from a
+; logical partition.
 ;
-VERBOSE		     EQU  1
+EXT_PART_SUPPORT     EQU  1
+
+CHS_SUPPORT          EQU  1
 
 ;
 ; Various constants.
@@ -64,38 +62,22 @@
 kBoot0RelocAddr      EQU  0xE000        ; boot0 relocated address
 
 kMBRBuffer           EQU  0x1000        ; MBR buffer address
-kLBA1Buffer          EQU  0x1200        ; LBA1 - GPT Partition Table Header buffer address
-kGPTABuffer	     EQU  0x1400        ; GUID Partition Entry Array buffer address
+kExtBuffer           EQU  0x1200        ; EXT boot block buffer address
 
 kPartTableOffset     EQU  0x1be
 kMBRPartTable        EQU  kMBRBuffer + kPartTableOffset
+kExtPartTable        EQU  kExtBuffer + kPartTableOffset
 
 kSectorBytes         EQU  512           ; sector size in bytes
 kBootSignature       EQU  0xAA55        ; boot sector signature
-kGPTSignatureLow     EQU  'EFI '	; GUID Partition Table Header Signature
-kGPTSignatureHigh    EQU  'PART'
-kGUIDLastDwordOffs   EQU  12		; last 4 byte offset of a GUID
 
 kPartCount           EQU  4             ; number of paritions per table
-kPartTypeHFS	     EQU  0xaf          ; HFS+ Filesystem type
-kPartTypePMBR        EQU  0xee		; On all GUID Partition Table disks a Protective MBR (PMBR)
-					; in LBA 0 (that is, the first block) precedes the
-					; GUID Partition Table Header to maintain compatibility
-					; with existing tools that do not understand GPT partition structures.
-					; The Protective MBR has the same format as a legacy MBR 
-					; and contains one partition entry with an OSType set to 0xEE
-					; reserving the entire space used on the disk by the GPT partitions,
-					; including all headers.
-
-kPartActive	     EQU  0x80		; active flag enabled
-kPartInactive	     EQU  0x00          ; active flag disabled
-kHFSGUID	     EQU  0x48465300    ; first 4 bytes of Apple HFS Partition Type GUID.
-kAppleGUID	     EQU  0xACEC4365	; last 4 bytes of Apple type GUIDs. 
-kEFISYSGUID	     EQU  0xC93EC93B    ; first 4 bytes of EFI System Partition Type GUID.
-
-
-; efi system C12A7328-F81F-11D2-BA4B-00A0C93EC93B
+kPartTypeBoot        EQU  0xab          ; boot2 partition type
+kPartTypeExtDOS      EQU  0x05          ; DOS extended partition type
+kPartTypeExtWin      EQU  0x0f          ; Windows extended partition type
+kPartTypeExtLinux    EQU  0x85          ; Linux extended partition type
 
+kPartActive	     EQU  0x80
 
 %ifdef FLOPPY
 kDriveNumber         EQU  0x00
@@ -110,51 +92,19 @@
 ; giving the size of the structure.
 ;
            struc part
-.bootid    resb 1      ; bootable or not 
-.head      resb 1      ; starting head, sector, cylinder
-.sect      resb 1      ;
-.cyl       resb 1      ;
-.type      resb 1      ; partition type
+.bootid:   resb 1      ; bootable or not 
+.head:     resb 1      ; starting head, sector, cylinder
+.sect:     resb 1      ;
+.cyl:      resb 1      ;
+.type:     resb 1      ; partition type
 .endhead   resb 1      ; ending head, sector, cylinder
-.endsect   resb 1      ;
-.endcyl    resb 1      ;
-.lba       resd 1      ; starting lba
+.endsect:  resb 1      ;
+.endcyl:   resb 1      ;
+.lba:      resd 1      ; starting lba
 .sectors   resd 1      ; size in sectors
            endstruc
 
 ;
-; Format of GPT Partition Table Header
-;
-				struc	gpth
-.Signature 			resb	8 
-.Revision  			resb	4
-.HeaderSize			resb	4
-.HeaderCRC32			resb	4
-.Reserved			resb	4
-.MyLBA				resb	8
-.AlternateLBA			resb	8
-.FirstUsableLBA			resb	8
-.LastUsableLBA			resb	8
-.DiskGUID			resb	16
-.PartitionEntryLBA		resb	8
-.NumberOfPartitionEntries	resb	4
-.SizeOfPartitionEntry		resb	4
-.PartitionEntryArrayCRC32	resb	4
-				endstruc
-
-;				
-; Format of GUID Partition Entry Array
-;
-				struc	gpta
-.PartitionTypeGUID		resb	16
-.UniquePartitionGUID		resb	16
-.StartingLBA			resb	8
-.EndingLBA			resb	8
-.Attributes			resb	8
-.PartitionName			resb	72
-				endstruc
-
-;
 ; Macros.
 ;
 %macro DebugCharMacro 1
@@ -162,11 +112,6 @@
     call  print_char
 %endmacro
 
-%macro LogString 1
-    mov   di, %1
-    call  log_string
-%endmacro
-
 %if DEBUG
 %define DebugChar(x)  DebugCharMacro x
 %else
@@ -178,12 +123,12 @@
 
     SEGMENT .text
 
-    ORG     kBoot0RelocAddr
-    
+    ORG     0xE000                  ; must match kBoot0RelocAddr
+
 ;--------------------------------------------------------------------------
 ; Boot code is loaded at 0:7C00h.
 ;
-start:
+start
     ;
     ; Set up the stack to grow down from kBoot0Segment:kBoot0Stack.
     ; Interrupts should be off while the stack is being manipulated.
@@ -202,14 +147,14 @@
     ;
     mov     si, kBoot0LoadAddr      ; si <- source
     mov     di, kBoot0RelocAddr     ; di <- destination
+    ;
     cld                             ; auto-increment SI and/or DI registers
     mov     cx, kSectorBytes/2      ; copy 256 words
     repnz   movsw                   ; repeat string move (word) operation
 
-    ;
     ; Code relocated, jump to start_reloc in relocated location.
     ;
-    jmp     kBoot0Segment:start_reloc
+    jmp     0:start_reloc
 
 ;--------------------------------------------------------------------------
 ; Start execution from the relocated location.
@@ -218,290 +163,265 @@
 
     DebugChar('>')
 
+.loop:
+
 %if DEBUG
     mov     al, dl
     call    print_hex
 %endif
 
     ;
-    ; Since this code may not always reside in the MBR, always start by
-    ; loading the MBR to kMBRBuffer and LBA1 to kGPTBuffer.
+    ; Clear various flags in memory.
     ;
-
     xor     eax, eax
-    mov     [my_lba], eax           ; store LBA sector 0 for read_lba function
-    mov     al, 2                   ; load two sectors: MBR and LBA1
+    mov     [first_part], eax        ; clear EBIOS LBA offset
+    mov     [this_part], eax
+
+%if CHS_SUPPORT
+    mov     [ebios_present], al     ; clear EBIOS support flag
+	
+    ;
+    ; Check if EBIOS is supported for this hard drive.
+    ;
+    mov     ah, 0x41                ; Function 0x41
+    mov     bx, 0x55AA              ; check signature
+    int     0x13
+
+    ;
+    ; If successful, the return values are as follows:
+    ;
+    ; carry = 0
+    ; ah    = major version of EBIOS extensions (0x21 = version 1.1)
+    ; al    = altered
+    ; bx    = 0xAA55
+    ; cx    = support bits. bit 0 must be set for function 0x42.
+    ;
+    jc      .ebios_check_done
+    cmp     bx, 0xAA55              ; check BX = 0xAA55
+    jnz     .ebios_check_done
+    test    cl, 0x01                ; check enhanced drive read support
+    setnz   [ebios_present]         ; EBIOS supported, set flag
+    DebugChar('E')                  ; EBIOS supported
+.ebios_check_done:
+%else
+    inc     al
+    mov     [ebios_present], al
+%endif
+
+    ;
+    ; Since this code may not always reside in the MBR, always start by
+    ; loading the MBR to kMBRBuffer.
+    ;
+    mov     al, 1                   ; load one sector
+    xor     bx, bx
+    mov     es, bx                  ; MBR load segment = 0
     mov     bx, kMBRBuffer          ; MBR load address
+    mov     si, bx                  ; pointer to fake partition entry
+%if CHS_SUPPORT
+    mov     WORD [si], 0x0000       ; CHS DX: head = 0
+    mov     WORD [si + 2], 0x0001   ; CHS CX: cylinder = 0, sector = 1
+%endif
+    mov     DWORD [si + part.lba], 0x00000000 ; LBA sector 0
+
     call    load
-    jc      error	            ; MBR load error
+    jc      .next_drive             ; MBR load error
 
     ;
     ; Look for the booter partition in the MBR partition table,
     ; which is at offset kMBRPartTable.
     ;
-    mov     si, kMBRPartTable       ; pointer to partition table
+    mov     di, kMBRPartTable       ; pointer to partition table
     call    find_boot               ; will not return on success
 
+.next_drive:
+    inc     dl                      ; next drive number
+    test    dl, 0x4                 ; went through all 4 drives?
+    jz      .loop                   ; not yet, loop again
+
 error:
-    LogString(boot_error_str)
+    mov     si, boot_error_str
+    call    print_string
 
 hang:
     hlt
-    jmp     hang
-
+    jmp     SHORT hang
 
 ;--------------------------------------------------------------------------
 ; Find the active (boot) partition and load the booter from the partition.
 ;
 ; Arguments:
 ;   DL = drive number (0x80 + unit number)
-;   SI = pointer to fdisk partition table.
+;   DI = pointer to fdisk partition table.
 ;
 ; Clobber list:
 ;   EAX, BX, EBP
 ;
 find_boot:
+    push    cx                      ; preserve CX and SI
+    push    si
 
     ;
     ; Check for boot block signature 0xAA55 following the 4 partition
     ; entries.
     ;
-    cmp     WORD [si + part_size * kPartCount], kBootSignature
-    jne	    .exit        	  			; boot signature not found.
-
-    xor	    bx, bx					; BL will be set to 1 later in case of
-							; Protective MBR has been found
+    cmp     WORD [di + part_size * kPartCount], kBootSignature
+    jne     NEAR .exit              ; boot signature not found
 
-    inc     bh						; BH = 1. Giving a chance for a second pass
-							; to boot an inactive but boot1h aware HFS+ partition
-							; by scanning the MBR partition entries again.
-
-.start_scan:							
-    mov     cx, kPartCount          			; number of partition entries per table
+    mov     si, di                  ; make SI a pointer to partition table
+    mov     cx, kPartCount          ; number of partition entries per table
 
 .loop:
-
     ;
     ; First scan through the partition table looking for the active
-    ; partition.
+    ; partition. Postpone walking the extended partition chain for
+    ; the second pass. Do not merge the two without changing the
+    ; buffering scheme used to store extended partition tables.
     ;
 %if DEBUG
     mov     al, [si + part.type]    ; print partition type
     call    print_hex
 %endif
 
-    mov	    eax, [si + part.lba]                        ; save starting LBA of current 
-    mov	    [my_lba], eax				; MBR partition entry for read_lba function
-    cmp     BYTE [si + part.type], 0			; unused partition?
-    je      .continue  					; skip to next entry
-    cmp	    BYTE [si + part.type], kPartTypePMBR	; check for Protective MBR 
-    jne	    .testPass
-
-    mov     BYTE [si + part.bootid], kPartInactive	; found Protective MBR
-        						; clear active flag to make sure this protective
-							; partition won't be used as a bootable partition.
-    mov	    bl, 1					; Assume we can deal with GPT but try to scan
-    							; later if not found any other bootable partitions.
-
-.testPass:
-    cmp	    bh, 1
-    jne	    .Pass2
-
-.Pass1:
-    cmp     BYTE [si + part.bootid], kPartActive	; In pass 1 we are walking on the standard path
-    jne     .continue					; by trying to hop on the active partition.
-    jmp    .tryToBoot
-
-.Pass2:    
-    cmp	    BYTE [si + part.type], kPartTypeHFS		; In pass 2 we're going to find a HFS+ partition
-    jne     .continue					; equipped with boot1h in its boot record
-							; regardless if it's active or not.    
+    cmp     BYTE [si + part.type], 0
+    je      .continue
+    cmp     BYTE [si + part.bootid], kPartActive
+    jne     .continue
 
     DebugChar('*')
 
+    ; fix offset for load
+    mov     eax, [this_part]
+    mov     [first_part], eax
+	
     ;
     ; Found boot partition, read boot sector to memory.
     ;
+    mov     al, 1
+    mov     bx, kBoot0Segment
+    mov     es, bx
+    mov     bx, kBoot0LoadAddr
+    call    load                    ; will not return on success
+    jc      error                   ; load error, keep looking?
 
-.tryToBoot:
-
-%if VERBOSE 
-    LogString(mbr_str)
-%endif
-
-    call    loadBootSector
-    jne     .continue
-    jmp	    initBootLoader
-
-.continue:
-    add     si, part_size          			; advance SI to next partition entry
-    loop    .loop                 		 	; loop through all partition entries
-
-    ;
-    ; Scanned all partitions but not found any with active flag enabled
-    ; Anyway if we found a protective MBR before we still have a chance 
-    ; for a possible GPT Header at LBA 1
-    ;    
-    dec	    bl
-    jz	    checkGPT					; found Protective MBR before
-
-    ;
-    ; Switching to Pass 2 
-    ; try to find a boot1h aware HFS+ MBR partition
-    ;
-    dec	    bh
-    mov	    si, kMBRPartTable				; set SI to first entry of MBR Partition table
-    jz      .start_scan					; scan again
-    
-.exit:
-    ret							; Giving up.
-    
     ; 
-    ; Found Protective MBR Partition Type: 0xEE
-    ; Check for 'EFI PART' string at the beginning
-    ; of LBA1 for possible GPT Table Header
-    ;
-checkGPT:
-
-    mov	    di, kLBA1Buffer				; address of GUID Partition Table Header
-    cmp	    DWORD [di], kGPTSignatureLow		; looking for 'EFI '
-    jne	    .exit					; not found. Giving up.
-    cmp	    DWORD [di + 4], kGPTSignatureHigh   	; looking for 'PART'
-    jne	    .exit					; not found. Giving up indeed.
-    mov	    si, di
-
-    ;
-    ; Loading GUID Partition Table Array
+    ; Fix up absolute block location in partition record.
     ;
-    mov     eax, [si + gpth.PartitionEntryLBA]          ; starting LBA of GPT Array
-    mov     [my_lba], eax				; save starting LBA for read_lba function
-    mov     cx, [si + gpth.NumberOfPartitionEntries]	; number of GUID Partition Array entries
-    mov     bx, [si + gpth.SizeOfPartitionEntry]	; size of GUID Partition Array entry
-    push    bx						; push size of GUID Partition entry
-
-    ;
-    ; Calculating number of sectors we need to read for loading a GPT Array
-    ;
-    push    dx						; preserve DX (DL = BIOS drive unit number)
-    mov	    ax, cx					; AX * BX = number of entries * size of one entry
-    mul     bx                                          ; AX = total byte size of GPT Array
-    pop	    dx						; restore DX
-    shr     ax, 9                                       ; convert to sectors
+    mov     eax, [si + part.lba]
+    add     eax, [this_part]
+    mov     [si + part.lba], eax
 
+    DebugChar('J')
     ;
-    ; ... or:
-    ; Current GPT Arrays uses 128 partition entries each 128 bytes long
-    ; 128 entries * 128 bytes long GPT Array entries / 512 bytes per sector = 32 sectors
+    ; Jump to partition booter. The drive number is already in register DL.
+    ; SI is pointing to the modified partition entry.
     ;
-;   mov	    al, 32					; maximum sector size of GPT Array (hardcoded method)
+    jmp     kBoot0Segment:kBoot0LoadAddr
 
-    mov	    bx, kGPTABuffer
-    push    bx						; push address of GPT Array
-    call    load					; read GPT Array
-    pop	    si						; SI = address of GPT Array
-    pop	    bx						; BX = size of GUID Partition Array entry
-    jc	    error
+.continue:
+    add     si, part_size           ; advance SI to next partition entry
+    loop    .loop                   ; loop through all partition entries
 
+%if EXT_PART_SUPPORT
     ;
-    ; Walk through GUID Partition Table Array
-    ; and load boot record from first available HFS+ partition.
-    ;
-    ; If it has boot signature (0xAA55) then jump to it
-    ; otherwise skip to next partition.
+    ; No primary (or logical) boot partition found in the current
+    ; partition table. Restart and look for extended partitions.
     ;
+    mov     si, di                  ; make SI a pointer to partition table
+    mov     cx, kPartCount          ; number of partition entries per table
 
-%if VERBOSE
-    LogString(gpt_str)
-%endif
+.ext_loop:
 
-.gpt_loop:
+    mov     al, [si + part.type]    ; AL <- partition type
 
-;   mov     eax, [si + gpta.PartitionTypeGUID]
-;   cmp	    eax, kHFSGUID				; check current GUID Partition for HFS GUID
-    mov     eax, [si + gpta.PartitionTypeGUID + kGUIDLastDwordOffs]
+    cmp     al, kPartTypeExtDOS     ; Extended DOS
+    je      .ext_load
 
-; turbo - also try efi system partition
-;    cmp     eax,kEFISYSGUID
-;    je      .gpt_ok
+    cmp     al, kPartTypeExtWin     ; Extended Windows(95)
+    je      .ext_load
 
-;    cmp	    eax, kAppleGUID				; check current GUID Partition for Apple's GUID type
-;    jne	    .gpt_continue
+    cmp     al, kPartTypeExtLinux   ; Extended Linux
+    je      .ext_load
 
-;.gpt_ok
+.ext_continue:
     ;
-    ; Found HFS Partition
+    ; Advance si to the next partition entry in the extended
+    ; partition table.
     ;
+    add     si, part_size           ; advance SI to next partition entry
+    loop    .ext_loop               ; loop through all partition entries
+    jmp     .exit                   ; boot partition not found
 
-%if VERBOSE
-    LogString(hfs_str)
-%endif
-
-    mov	    eax, [si + gpta.StartingLBA]		; load boot sector from StartingLBA
-    mov	    [my_lba], eax		
-    call    loadBootSector
-    jne	    .gpt_continue				; no boot loader signature
-
-%if VERBOSE
-    LogString(bootable_str)
-%endif
-
-    mov	    si, kMBRPartTable				; fake the current GUID Partition
-    mov	    [si + part.lba], eax			; as MBR style partition for boot1h
-    mov     BYTE [si + part.type], kPartTypeHFS		; with HFS+ filesystem type (0xAF)
-    jmp	    SHORT initBootLoader    
-    
-.gpt_continue:
-
-    add	    si, bx					; advance SI to next partition entry
-    loop    .gpt_loop					; loop through all partition entries	
+.ext_load:
+    DebugChar('L')
 
-.exit:
-    ret							; no more GUID partitions. Giving up.
+    ; Save current partition offset, since for extended
+    ; partitions we will overwrite it when loading the new
+    ; table.
+    ; 
+    mov     ebp, [si + part.lba]
+	
+    ;
+    ; Setup the arguments for the load function call to bring the
+    ; extended partition table into memory.
+    ; Remember that SI points to the extended partition entry.
+    ;
+    mov     al, 1                   ; read 1 sector
+    xor     bx, bx
+    mov     es, bx                  ; es = 0
+    mov     bx, kExtBuffer          ; load extended boot sector
+    call    load
+    jc      .ext_continue           ; load error
 
-    DebugChar('J')
     ;
-    ; Jump to partition booter. The drive number is already in register DL.
-    ; SI is pointing to the modified partition entry.
+    ; The LBA address of all extended partitions is relative based
+    ; on the LBA address of the extended partition in the MBR, or
+    ; the extended partition at the head of the chain. Thus it is
+    ; necessary to save the LBA address of the first extended partition.
     ;
-initBootLoader:    
-
-%if VERBOSE
-    LogString(done_str)
-%endif
+	
+    DebugChar('+')	
 
-    jmp     kBoot0LoadAddr
+    add     ebp, [first_part]
+    mov     [this_part], ebp
 
+    mov     eax,[first_part]
+    or      eax, eax
+    jnz     .ext_find_boot
+    mov     [first_part], ebp
+	
+%if DEBUG
+        DebugChar('=')
+        mov eax, ebp
+        call print_hex
+%endif
 
-;--------------------------------------------------------------------------
-; loadBS - Load boot sector
-;
-; Arguments:
-;   DL = drive number (0x80 + unit number)
-;   [my_lba] = starting LBA.
-;
-; Returns:
-;   ZF = 0 if boot sector hasn't kBootSignature
-;        1 if boot sector has kBootSignature
-;
-loadBootSector:
-    pusha
-    
-    mov     al, 1
-    mov     bx, kBoot0LoadAddr
-    call    load                    ; will not return on success
-    jc      error                   ; load error, keep looking?
+.ext_find_boot:
+	
+    ;
+    ; Call find_boot recursively to scan through the extended partition
+    ; table. Load DI with a pointer to the extended table in memory.
+    ;
+    mov     di, kExtPartTable       ; partition table pointer
+    call    find_boot               ; recursion...
 
     ;
-    ; Check for boot block signature 0xAA55
+    ; Since there is an "unwritten" rule that limits each partition table
+    ; to have 0 or 1 extended partitions, there is no point in looking for
+    ; any additional extended partition entries at this point. There is no
+    ; boot partition linked beyond the extended partition that was loaded
+    ; above.
     ;
-    mov	    di, bx
-    cmp     WORD [di + kSectorBytes - 2], kBootSignature
 
-    popa
+%endif ; EXT_PART_SUPPORT
 
+.exit:
+    ;
+    ; Boot partition not found. Giving up.
+    ;
+    pop     si
+    pop     cx
     ret
 
-
 ;--------------------------------------------------------------------------
 ; load - Load one or more sectors from a partition.
 ;
@@ -509,7 +429,7 @@
 ;   AL = number of 512-byte sectors to read.
 ;   ES:BX = pointer to where the sectors should be stored.
 ;   DL = drive number (0x80 + unit number)
-;   [my_lba] = starting LBA.
+;   SI = pointer to the partition entry.
 ;
 ; Returns:
 ;   CF = 0 success
@@ -517,6 +437,10 @@
 ;
 load:
     push    cx
+%if CHS_SUPPORT
+    test    BYTE [ebios_present], 1
+    jz      .chs
+%endif
 
 .ebios:
     mov     cx, 5                   ; load retry count
@@ -525,10 +449,80 @@
     jnc     .exit
     loop    .ebios_loop
 
-.exit:
+%if CHS_SUPPORT
+.chs:
+    mov     cx, 5                   ; load retry count
+.chs_loop:
+    call    read_chs                ; use INT13/F2
+    jnc     .exit
+    loop    .chs_loop
+%endif
+
+.exit
     pop     cx
     ret
 
+%if CHS_SUPPORT
+;--------------------------------------------------------------------------
+; read_chs - Read sectors from a partition using CHS addressing.
+;
+; Arguments:
+;   AL = number of 512-byte sectors to read.
+;   ES:BX = pointer to where the sectors should be stored.
+;   DL = drive number (0x80 + unit number)
+;   SI = pointer to the partition entry.
+;
+; Returns:
+;   CF = 0 success
+;        1 error
+;
+read_chs:
+    pusha                           ; save all registers
+
+    ;
+    ; Read the CHS start values from the partition entry.
+    ;
+    mov     dh, [ si + part.head ]  ; drive head
+    mov     cx, [ si + part.sect ]  ; drive sector + cylinder
+
+    ;
+    ; INT13 Func 2 - Read Disk Sectors
+    ;
+    ; Arguments:
+    ;   AH    = 2
+    ;   AL    = number of sectors to read
+    ;   CH    = lowest 8 bits of the 10-bit cylinder number
+    ;   CL    = bits 6 & 7: cylinder number bits 8 and 9
+    ;           bits 0 - 5: starting sector number (1-63)
+    ;   DH    = starting head number (0 to 255)
+    ;   DL    = drive number (80h + drive unit)
+    ;   es:bx = pointer where to place sectors read from disk
+    ;
+    ; Returns:
+    ;   AH    = return status (sucess is 0)
+    ;   AL    = burst error length if ah=0x11 (ECC corrected)
+    ;   carry = 0 success
+    ;           1 error
+    ;
+    mov     ah, 0x02                ; Func 2
+    int     0x13                    ; INT 13
+    jnc     .exit
+
+    DebugChar('r')                  ; indicate INT13/F2 error
+
+    ;
+    ; Issue a disk reset on error.
+    ; Should this be changed to Func 0xD to skip the diskette controller
+    ; reset?
+    ;
+    xor     ax, ax                  ; Func 0
+    int     0x13                    ; INT 13
+    stc                             ; set carry to indicate error
+
+.exit:
+    popa
+    ret
+%endif
 
 ;--------------------------------------------------------------------------
 ; read_lba - Read sectors from a partition using LBA addressing.
@@ -537,7 +531,7 @@
 ;   AL = number of 512-byte sectors to read (valid from 1-127).
 ;   ES:BX = pointer to where the sectors should be stored.
 ;   DL = drive number (0x80 + unit number)
-;   [my_lba] = starting LBA.
+;   SI = pointer to the partition entry.
 ;
 ; Returns:
 ;   CF = 0 success
@@ -552,13 +546,18 @@
     ; INT13/F42 (Extended Read Sectors) on the stack.
     ;
 
-;   push    DWORD 0                 ; offset 12, upper 32-bit LBA
+    ; push    DWORD 0               ; offset 12, upper 32-bit LBA
     push    ds                      ; For sake of saving memory,
     push    ds                      ; push DS register, which is 0.
-    mov     ecx, [my_lba]           ; offset 8, lower 32-bit LBA
+
+    mov     ecx, [first_part]        ; offset 8, lower 32-bit LBA
+    add     ecx, [si + part.lba]
     push    ecx
+
     push    es                      ; offset 6, memory segment
+
     push    bx                      ; offset 4, memory offset
+
     xor     ah, ah                  ; offset 3, must be 0
     push    ax                      ; offset 2, number of sectors
 
@@ -608,31 +607,6 @@
     popa
     ret
 
-    
-;--------------------------------------------------------------------------
-; Write a string with 'boot0: ' prefix to the console.
-;
-; Arguments:
-;   ES:DI   pointer to a NULL terminated string.
-;
-; Clobber list:
-;   DI
-;
-log_string:
-    pusha
-        
-    push	di
-    mov		si, log_title_str
-    call	print_string
-
-    pop		si
-    call	print_string
-
-    popa
-    
-    ret
-
-    
 ;--------------------------------------------------------------------------
 ; Write a string to the console.
 ;
@@ -642,29 +616,27 @@
 ; Clobber list:
 ;   AX, BX, SI
 ;
-print_string:
+print_string
     mov     bx, 1                   ; BH=0, BL=1 (blue)
     cld                             ; increment SI after each lodsb call
-.loop:
+.loop
     lodsb                           ; load a byte from DS:SI into AL
     cmp     al, 0                   ; Is it a NULL?
     je      .exit                   ; yes, all done
     mov     ah, 0xE                 ; INT10 Func 0xE
     int     0x10                    ; display byte in tty mode
     jmp     short .loop
-.exit:
+.exit
     ret
 
 
-%if DEBUG
-
 ;--------------------------------------------------------------------------
 ; Write a ASCII character to the console.
 ;
 ; Arguments:
 ;   AL = ASCII character.
 ;
-print_char:
+print_char
     pusha
     mov     bx, 1                   ; BH=0, BL=1 (blue)
     mov     ah, 0x0e                ; bios INT 10, Function 0xE
@@ -672,7 +644,8 @@
     popa
     ret
 
-
+%if DEBUG
+	
 ;--------------------------------------------------------------------------
 ; Write the 4-byte value to the console in hex.
 ;
@@ -683,7 +656,7 @@
     pushad
     mov     cx, WORD 4
     bswap   eax
-.loop:
+.loop
     push    ax
     ror     al, 4
     call    print_nibble            ; display upper nibble
@@ -696,7 +669,6 @@
     call    print_char
     mov     al, 13
     call    print_char
-
     popad
     ret
 	
@@ -722,16 +694,7 @@
 ;--------------------------------------------------------------------------
 ; NULL terminated strings.
 ;
-log_title_str		db  10, 13, 'boot0: ', 0
-boot_error_str   	db  'error', 0
-
-%if VERBOSE
-gpt_str			db  'GPT', 0
-mbr_str			db  'MBR', 0
-hfs_str			db  'HFS+', 0
-bootable_str		db  'booting', 0
-done_str		db  'done', 0
-%endif
+boot_error_str   db  10, 13, 'b0 error', 0
 
 ;--------------------------------------------------------------------------
 ; Pad the rest of the 512 byte sized booter with zeroes. The last
@@ -740,12 +703,8 @@
 ; If the booter code becomes too large, then nasm will complain
 ; that the 'times' argument is negative.
 
-;
-; According to EFI specification, maximum boot code size is 440 bytes 
-;
-
-pad_boot:
-    times 440-($-$$) db 0
+pad_boot
+    times 446-($-$$) db 0
 
 %ifdef FLOPPY
 ;--------------------------------------------------------------------------
@@ -768,7 +727,7 @@
 part2numsect    dd    0x000015fe    ; 2.88MB - 65K
 %endif
 
-pad_table_and_sig:
+pad_table_and_sig
     times 510-($-$$) db 0
     dw    kBootSignature
 	
@@ -778,6 +737,8 @@
 ;
 ; In memory variables.
 ;
-my_lba			resd	1	; Starting LBA for read_lba function
-
-; END
+first_part      resd   1   ; starting LBA of the intial extended partition.
+this_part       resd   1   ; starting LBA of the current extended partition. 
+ebios_present   resb   1   ; 1 if EBIOS is supported, 0 otherwise.
+        
+    END
diff -Naur v51_src/i386/boot2/boot.c boot-132_dfe_r146/i386/boot2/boot.c
--- v51_src/i386/boot2/boot.c	2008-10-02 03:46:06.000000000 +0200
+++ boot-132_dfe_r146/i386/boot2/boot.c	2008-06-28 21:53:02.000000000 +0200
@@ -65,7 +65,6 @@
 char gRootDevice[512];
 char gMKextName[512];
 BVRef gBootVolume;
-extern BVRef gBIOSBootVolume; // turbo - original partition
 
 static void selectBiosDevice(void);
 
@@ -224,29 +223,6 @@
     // PCI_Bus_Init( &bootInfo->pciInfo );
 }
 
-#define BooterKextDir "/System/Booter/"
-
-static long turbo_preLoadDrivers(LoadDriverMKext_t LoadDriverMKext_p, FileLoadDrivers_t FileLoadDrivers_p) {
- char dirspec[1024]; // nasty hack because FileLoadDrivers will overwrite our string!!
- 
- verbose("turbo_LoadExtraDrivers active\n");
-
- // Search for Extensions in BooterKextDir on our original BOOT volume
- if (gBIOSBootVolume) {
-  //setRootVolume(gBIOSBootVolume);
-  sprintf(dirspec,"bt(0,0)%s",BooterKextDir);
-  verbose("%s: Scanning BIOS Boot (%s)\n",__FUNCTION__,dirspec);
-  if (FileLoadDrivers_p(dirspec,0)==0) verbose("%s: Loaded from BIOS Boot!\n", __FUNCTION__);
- }
-
- // Search the same path on our chosen root
- strcpy(dirspec,BooterKextDir); // required because it will overwrite our (const) string!
- verbose("%s: Scanning selected Boot (%s)\n",__FUNCTION__,dirspec);
- if (FileLoadDrivers_p(dirspec,0)==0) verbose("%s: Loaded from selected Boot!\n", __FUNCTION__);
-
- return(0);
-}
-
 /*!
     This is the entrypoint from real-mode which functions exactly as it did before.
     Multiboot does its own runtime initialization, does some of its own things, and then
@@ -324,14 +300,8 @@
 
     // Record default boot device.
     gBootVolume = selectBootVolume(bvChain);
-
-    // turbo - Save the ORIGINAL boot volume too for loading our mkext
-    if (!gBIOSBootVolume) gBIOSBootVolume = gBootVolume;
-    // turbo - hook our driver preload routine
-    LoadExtraDrivers_p=&turbo_preLoadDrivers;
- 
     setRootVolume(gBootVolume);
-    
+
     // Load default config file from boot device.
     status = loadSystemConfig(0, 0);
 
diff -Naur v51_src/i386/boot2/boot.h boot-132_dfe_r146/i386/boot2/boot.h
--- v51_src/i386/boot2/boot.h	2008-10-02 03:46:06.000000000 +0200
+++ boot-132_dfe_r146/i386/boot2/boot.h	2008-06-28 21:48:57.000000000 +0200
@@ -130,15 +130,11 @@
 extern long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize);
 
 typedef long (*FileLoadDrivers_t)(char *dirSpec, long plugin);
-typedef long (*LoadDriverMKext_t)(char *fileSpec);
-
 /*!
     Hookable function pointer called during the driver loading phase that
     allows other code to cause additional drivers to be loaded.
  */
-// turbo - allow extra mkext also
-//extern long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
-extern long (*LoadExtraDrivers_p)(LoadDriverMKext_t LoadDriverMKext_p, FileLoadDrivers_t FileLoadDrivers_p);
+extern long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
 
 /*
  * options.c
diff -Naur v51_src/i386/boot2/drivers.c boot-132_dfe_r146/i386/boot2/drivers.c
--- v51_src/i386/boot2/drivers.c	2008-10-02 03:46:06.000000000 +0200
+++ boot-132_dfe_r146/i386/boot2/drivers.c	2008-06-27 06:20:27.000000000 +0200
@@ -76,7 +76,7 @@
   kCFBundleType3
 };
 
-long (*LoadExtraDrivers_p)(LoadDriverMKext_t LoadDriverMKext_p, FileLoadDrivers_t FileLoadDrivers_p);
+long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
 
 static unsigned long Alder32( unsigned char * buffer, long length );
 
@@ -162,7 +162,7 @@
     // Load extra drivers if a hook has been installed.
     if (LoadExtraDrivers_p != NULL)
     {
-        long ret = (*LoadExtraDrivers_p)(&LoadDriverMKext,&FileLoadDrivers); // turbo - support directly loading an mkext also
+        long ret = (*LoadExtraDrivers_p)(&FileLoadDrivers);
         if(ret != 0)
             return ret;
     }
@@ -183,12 +183,10 @@
             if ( LoadDriverMKext(gMKextName) != 0 )
             {
                 error("Could not load %s\n", gMKextName);
-                // turbo - not fatal
-                //return -1;
+                return -1;
             }
         }
-// turbo - load both mkexts!
-//      else
+        else
         {
             strcpy(gExtensionsSpec, dirSpec);
             strcat(gExtensionsSpec, "System/Library/");
@@ -478,8 +476,8 @@
                 sprintf(gFileSpec, "%s%s", module->driverPath, fileName);
                 length = LoadThinFatFile(gFileSpec, &driverModuleAddr);
                 //length = LoadFile(gFileSpec);
-                driverModuleAddr = (void *)driverModuleAddr;
-                printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); //getc();
+                //driverModuleAddr = (void *)kLoadAddr;
+                //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc();
             }
             else
                 length = 0;
diff -Naur v51_src/i386/boot2/mboot.c boot-132_dfe_r146/i386/boot2/mboot.c
--- v51_src/i386/boot2/mboot.c	2008-10-02 03:46:06.000000000 +0200
+++ boot-132_dfe_r146/i386/boot2/mboot.c	2008-06-29 05:40:52.000000000 +0200
@@ -45,7 +45,7 @@
                       unsigned int byteoff,
                       unsigned int byteCount, void * buffer );
 static int multiboot_get_ramdisk_info(int biosdev, struct driveInfo *dip);
-static long multiboot_LoadExtraDrivers(LoadDriverMKext_t LoadDriverMKext_p, FileLoadDrivers_t FileLoadDrivers_p);
+static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p);
 
 // Starts off in the multiboot context 1 MB high but eventually gets into low memory
 // and winds up with a bootdevice in eax which is all that boot() wants
@@ -443,7 +443,7 @@
     return 0;
 }
 
-static long multiboot_LoadExtraDrivers(LoadDriverMKext_t LoadDriverMKext_p, FileLoadDrivers_t FileLoadDrivers_p)
+static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p)
 {
     char extensionsSpec[1024];
     int ramdiskUnit;
diff -Naur v51_src/i386/libsaio/biosfn.c boot-132_dfe_r146/i386/libsaio/biosfn.c
--- v51_src/i386/libsaio/biosfn.c	2008-10-06 02:54:40.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/biosfn.c	2008-06-29 05:51:25.000000000 +0200
@@ -327,42 +327,42 @@
     return bb.eax.r.h;
 }
 
-//int ebioswrite(int dev, long sec, int count)
-//{
-//    int i;
-//    static struct {
-//        unsigned char  size;
-//        unsigned char  reserved;
-//        unsigned char  numblocks;
-//        unsigned char  reserved2;
-//        unsigned short bufferOffset;
-//        unsigned short bufferSegment;
-//        unsigned long  long startblock;
-//    } addrpacket __attribute__((aligned(16))) = {0};
-//    addrpacket.size = sizeof(addrpacket);
-//
-//    for (i=0;;) {
-//        bb.intno   = 0x13;
-//        bb.eax.r.l = 0; /* Don't verify */
-//        bb.eax.r.h = 0x43;
-//        bb.edx.r.l = dev;
-//        bb.esi.rr  = NORMALIZED_OFFSET((unsigned)&addrpacket);
-//        bb.ds      = NORMALIZED_SEGMENT((unsigned)&addrpacket);
-//        addrpacket.reserved = addrpacket.reserved2 = 0;
-//        addrpacket.numblocks     = count;
-//        addrpacket.bufferOffset  = OFFSET(ptov(BIOS_ADDR));
-//        addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
-//        addrpacket.startblock    = sec;
-//        bios(&bb);
-//        if ((bb.eax.r.h == 0x00) || (i++ >= 5))
-//            break;
-//
-//        /* reset disk subsystem and try again */
-//        bb.eax.r.h = 0x00;
-//        bios(&bb);
-//    }
-//    return bb.eax.r.h;
-//}
+int ebioswrite(int dev, long sec, int count)
+{
+    int i;
+    static struct {
+        unsigned char  size;
+        unsigned char  reserved;
+        unsigned char  numblocks;
+        unsigned char  reserved2;
+        unsigned short bufferOffset;
+        unsigned short bufferSegment;
+        unsigned long  long startblock;
+    } addrpacket __attribute__((aligned(16))) = {0};
+    addrpacket.size = sizeof(addrpacket);
+
+    for (i=0;;) {
+        bb.intno   = 0x13;
+        bb.eax.r.l = 0; /* Don't verify */
+        bb.eax.r.h = 0x43;
+        bb.edx.r.l = dev;
+        bb.esi.rr  = NORMALIZED_OFFSET((unsigned)&addrpacket);
+        bb.ds      = NORMALIZED_SEGMENT((unsigned)&addrpacket);
+        addrpacket.reserved = addrpacket.reserved2 = 0;
+        addrpacket.numblocks     = count;
+        addrpacket.bufferOffset  = OFFSET(ptov(BIOS_ADDR));
+        addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
+        addrpacket.startblock    = sec;
+        bios(&bb);
+        if ((bb.eax.r.h == 0x00) || (i++ >= 5))
+            break;
+
+        /* reset disk subsystem and try again */
+        bb.eax.r.h = 0x00;
+        bios(&bb);
+    }
+    return bb.eax.r.h;
+}
 
 void putc(int ch)
 {
diff -Naur v51_src/i386/libsaio/disk.c boot-132_dfe_r146/i386/libsaio/disk.c
--- v51_src/i386/libsaio/disk.c	2008-10-06 02:53:46.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/disk.c	2008-06-26 07:38:02.000000000 +0200
@@ -114,9 +114,6 @@
 static struct DiskBVMap * gDiskBVMap  = NULL;
 static struct disk_blk0 * gBootSector = NULL;
 
-// Turbo - save what we think is our original BIOS boot volume if we have one 0xab
-BVRef gBIOSBootVolume = NULL;
-
 // Function pointers to be filled in if ramdisks are available:
 int (*p_ramdiskReadBytes)( int biosdev, unsigned int blkno,
                       unsigned int byteoff,
@@ -779,27 +776,7 @@
 				      kBIOSDevTypeHardDrive);
                         break;
 
-                    // turbo - we want the booter type scanned also
-                    case FDISK_BOOTER:
-                        if (part->bootid & FDISK_ACTIVE)
-                        gBIOSBootVolume = newFDiskBVRef(
-                                      biosdev, partno,
-                                      part->relsect,
-                                      part,
-                                      HFSInitPartition,
-                                      HFSLoadFile,
-                                      HFSReadFile,
-                                      HFSGetDirEntry,
-                                      HFSGetFileBlock,
-                                      HFSGetUUID,
-                                      HFSGetDescription,
-                                      HFSFree,
-                                      0,
-				      kBIOSDevTypeHardDrive);
-                        break;
-
-#if 0==1
-//#if UFS_SUPPORT
+#if UFS_SUPPORT
                     case FDISK_BOOTER:
                         booterUFS = newFDiskBVRef(
                                       biosdev, partno,
@@ -1019,13 +996,7 @@
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 // HFS+ GUID in LE form
-EFI_GUID const GPT_HFS_GUID	= { 0x48465300, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
-// turbo - also our booter partition
-EFI_GUID const GPT_BOOT_GUID	= { 0x426F6F74, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
-// turbo - or an efi system partition
-EFI_GUID const GPT_EFISYS_GUID	= { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B } };
-
-//C12A7328-F81F-11D2-BA4B-00A0C93EC93B
+EFI_GUID const GPT_HFS_GUID = { 0x48465300, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
 
 static BVRef diskScanGPTBootVolumes( int biosdev, int * countPtr )
 {
@@ -1173,25 +1144,7 @@
                 map->bvr = bvr;
                 ++map->bvrcnt;
             }
-
-            // turbo - save our booter partition
-            if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ||
-                 (efi_guid_compare(&GPT_EFISYS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ) {
-                  gBIOSBootVolume = newGPTBVRef(
-                                      biosdev, gptID,
-                                      gptMap->ent_lba_start,
-                                      gptMap,
-                                      HFSInitPartition,
-                                      HFSLoadFile,
-                                      HFSReadFile,
-                                      HFSGetDirEntry,
-                                      HFSGetFileBlock,
-                                      HFSGetUUID,
-                                      HFSGetDescription,
-                                      HFSFree,
-                                      0,
-				      kBIOSDevTypeHardDrive);
-            }            
+            
         }
     }
 
@@ -1487,41 +1440,41 @@
     return 0;
 }
 
-//int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )
-//{
-//    int secs;
-//    unsigned char *cbuf = (unsigned char *)buffer;
-//    unsigned int copy_len;
-//    int rc;
-//
-//    if ((len & (BPS-1)) != 0) {
-//        error("raw disk write not sector aligned");
-//        return -1;
-//    }
-//    secno += bvr->part_boff;
-//
-//    cache_valid = FALSE;
-//
-//    while (len > 0) {
-//        secs = len / BPS;
-//        if (secs > N_CACHE_SECS) secs = N_CACHE_SECS;
-//        copy_len = secs * BPS;
-//
-//        bcopy( cbuf, trackbuf, copy_len );
-//        //printf("rdr: ebioswrite(%d, %d, %d)\n", bvr->biosdev, secno, secs);
-//        if ((rc = ebioswrite(bvr->biosdev, secno, secs)) != 0) {
-//            error("  EBIOS write error: %s\n", bios_error(rc), rc);
-//            error("    Block %d Sectors %d\n", secno, secs);
-//            return rc;
-//        }
-//        len -= copy_len;
-//        cbuf += copy_len;
-//        secno += secs;
-//        spinActivityIndicator();
-//    }
-//
-//    return 0;
-//}
+int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )
+{
+    int secs;
+    unsigned char *cbuf = (unsigned char *)buffer;
+    unsigned int copy_len;
+    int rc;
+
+    if ((len & (BPS-1)) != 0) {
+        error("raw disk write not sector aligned");
+        return -1;
+    }
+    secno += bvr->part_boff;
+
+    cache_valid = FALSE;
+
+    while (len > 0) {
+        secs = len / BPS;
+        if (secs > N_CACHE_SECS) secs = N_CACHE_SECS;
+        copy_len = secs * BPS;
+
+        bcopy( cbuf, trackbuf, copy_len );
+        //printf("rdr: ebioswrite(%d, %d, %d)\n", bvr->biosdev, secno, secs);
+        if ((rc = ebioswrite(bvr->biosdev, secno, secs)) != 0) {
+            error("  EBIOS write error: %s\n", bios_error(rc), rc);
+            error("    Block %d Sectors %d\n", secno, secs);
+            return rc;
+        }
+        len -= copy_len;
+        cbuf += copy_len;
+        secno += secs;
+        spinActivityIndicator();
+    }
+
+    return 0;
+}
 
 
 int diskIsCDROM(BVRef bvr)
diff -Naur v51_src/i386/libsaio/fake_efi.c boot-132_dfe_r146/i386/libsaio/fake_efi.c
--- v51_src/i386/libsaio/fake_efi.c	2008-10-09 02:07:46.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/fake_efi.c	2008-05-25 06:52:31.000000000 +0200
@@ -251,54 +251,19 @@
 #define Tera (kilo * Giga)
 #define Peta (kilo * Tera)
 
-#define bit(n)		(1UL << (n))
-#define bitmask(h,l)	((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
-#define bitfield(x,h,l)	(((x) & bitmask(h,l)) >> l)
-
-#define TICKS				59659			/* Program counter to 50 ms = 59659 clks */
-#define IA32_PERF_STATUS	0x198
-#define K8_FIDVID_STATUS	0xC0010042
-#define K10_COFVID_STATUS	0xC0010071
-
-#define DEFAULT_FSB			100000          /* for now, hardcoding 100MHz for old CPUs */
-
-#define DEBUG_FSB 0
-#if DEBUG_FSB
-#define DBG(x...)	printf(x)
-#else
-#define DBG(x...)
-#endif
-
-uint64_t fsbFrequency;
-uint16_t div = 0; // Non-Integer Bus Ratio
-/* This should be const but DT__AddProperty takes char* */
-static char FSB_Frequency_prop[] = "FSBFrequency";
-
-
+/*==========================================================================
+ * FSB Frequency detection
+ */
+// DFE: rdtsc64 from xnu (obvious implementation)
 static inline uint64_t rdtsc64(void)
 {
-	uint64_t ret;
-	__asm__ volatile("rdtsc" : "=A" (ret));
-	return ret;
-}
-
-static inline uint64_t rdmsr64(uint32_t msr)
-{
     uint64_t ret;
-    __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
+    __asm__ volatile("rdtsc" : "=A" (ret));
     return ret;
 }
 
-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)
-	);
-}
+// DFE: enable_PIT2 and disable_PIT2 come from older xnu
+
 /*
  * Enable or disable timer 2.
  * Port 0x61 controls timer 2:
@@ -308,72 +273,26 @@
 inline static void
 enable_PIT2(void)
 {
-    asm volatile(
-        " inb   $0x61,%%al	\n\t"
-        " and   $0xFC,%%al	\n\t"
-        " or    $1,%%al		\n\t"
-        " outb  %%al,$0x61	\n\t"
+    /* Enable gate, disable speaker */
+    __asm__ volatile(
+        " inb   $0x61,%%al      \n\t"
+        " and   $0xFC,%%al       \n\t"  /* & ~0x03 */
+        " or    $1,%%al         \n\t"
+        " outb  %%al,$0x61      \n\t"
         : : : "%al" );
 }
 
 inline static void
 disable_PIT2(void)
 {
-    asm volatile(
-        " inb   $0x61,%%al	\n\t"
-        " and   $0xFC,%%al	\n\t"
-        " outb  %%al,$0x61	\n\t"
+    /* Disable gate and output to speaker */
+    __asm__ volatile(
+        " inb   $0x61,%%al      \n\t"
+        " and   $0xFC,%%al      \n\t"	/* & ~0x03 */
+        " outb  %%al,$0x61      \n\t"
         : : : "%al" );
 }
 
-inline static void
-set_PIT2(int value)
-{
-/*
- * First, tell the clock we are going to write 16 bits to the counter
- *   and enable one-shot mode (command 0xB8 to port 0x43)
- * Then write the two bytes into the PIT2 clock register (port 0x42).
- * Loop until the value is "realized" in the clock,
- * this happens on the next tick.
- */
-    asm volatile(
-        " movb  $0xB8,%%al	\n\t"
-        " outb	%%al,$0x43	\n\t"
-        " movb	%%dl,%%al	\n\t"
-        " outb	%%al,$0x42	\n\t"
-        " movb	%%dh,%%al	\n\t"
-        " outb	%%al,$0x42	\n"
-"1:	inb	$0x42,%%al	\n\t" 
-        " inb	$0x42,%%al	\n\t"
-        " cmp	%%al,%%dh	\n\t"
-        " jne	1b"
-        : : "d"(value) : "%al");
-}
-
-inline static uint64_t
-get_PIT2(unsigned int *value)
-{
-    register uint64_t	result;
-/*
- * This routine first latches the time (command 0x80 to port 0x43),
- * then gets the time stamp so we know how long the read will take later.
- * Read (from port 0x42) and return the current value of the timer.
- */
-    asm volatile(
-        " xorl	%%ecx,%%ecx	\n\t"
-        " movb	$0x80,%%al	\n\t"
-        " outb	%%al,$0x43	\n\t"
-        " rdtsc			\n\t"
-        " pushl	%%eax		\n\t"
-        " inb	$0x42,%%al	\n\t"
-        " movb	%%al,%%cl	\n\t"
-        " inb	$0x42,%%al	\n\t"
-        " movb	%%al,%%ch	\n\t"
-        " popl	%%eax	"
-        : "=A"(result), "=c"(*value));
-    return result;
-}
-
 // DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
 // roughly based on Linux code
 
@@ -481,150 +400,96 @@
     return retval;
 }
 
-/*
- * timeRDTSC() (from an old version of xnu)
- * This routine sets up PIT counter 2 to count down 1/20 of a second.
- * It pauses until the value is latched in the counter
- * and then reads the time stamp counter to return to the caller.
- */
-static uint64_t
-timeRDTSC(void)
+static inline uint64_t rdmsr64(uint32_t msr)
 {
-    int		attempts = 0;
-    uint64_t	latchTime;
-    uint64_t	saveTime,intermediate;
-    unsigned int timerValue, lastValue;
-
-    /*
-     * Table of correction factors to account for
-     *   - timer counter quantization errors, and
-     *   - undercounts 0..5
-     */
-#define CLKNUM		1193182		/* formerly 1193167 */
-#define	SAMPLE_CLKS_EXACT	(((double) CLKNUM) / 20.0)
-#define	SAMPLE_CLKS_INT		((int) CLKNUM / 20)
-#define SAMPLE_NSECS		(2000000000LL)
-#define SAMPLE_MULTIPLIER	(((double)SAMPLE_NSECS)*SAMPLE_CLKS_EXACT)
-#define ROUND64(x)		((uint64_t)((x) + 0.5))
-    uint64_t	scale[6] = {
-	ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-0)), 
-	ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-1)), 
-	ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-2)), 
-	ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-3)), 
-	ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-4)), 
-	ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-5))
-    };
-                            
-    
-restart:
-    if (attempts >= 2)
-//		printf("calibration failed with %d attempts\n", attempts);
-    attempts++;
-    enable_PIT2();   					// turn on PIT2
-    set_PIT2(0);					// reset timer 2 to be zero
-    latchTime = rdtsc64();				// get the time stamp to time 
-    latchTime = get_PIT2(&timerValue) - latchTime;	// time how long this takes
-    set_PIT2(SAMPLE_CLKS_INT);				// set up the timer for (almost) 1/20th a second
-    saveTime = rdtsc64();				// now time how long a 20th a second is...
-    get_PIT2(&lastValue);
-    get_PIT2(&lastValue);				// read twice, first value may be unreliable
-    do {
-        intermediate = get_PIT2(&timerValue);
-        if (timerValue > lastValue) {
-	    set_PIT2(0);
-	    disable_PIT2();
-	    goto restart;
-	}
-        lastValue = timerValue;
-    } while (timerValue > 5);
-    intermediate -= saveTime;		// raw count for about 1/20 second
-    intermediate *= scale[timerValue];	// rescale measured time spent
-    intermediate /= SAMPLE_NSECS;	// so its exactly 1/20 a second
-    intermediate += latchTime;		// add on our save fudge
-    
-    set_PIT2(0);			// reset timer 2 to be zero
-    disable_PIT2();     		// turn off PIT 2
-
-    return intermediate;
-}
-
-static uint64_t getCPUFrequency(void)
-{
-	uint64_t tsc_freq = 0;
-	tsc_freq = (timeRDTSC() * 20);
-//	printf("CPU Frequency = %dMHz \n", (tsc_freq / 1000000));
-	return(tsc_freq);
-}
-
-static int getCPUMultiplier(void)
-{
-	uint32_t	cpuid_reg[4];
-	uint32_t	cpu_vendor;
-	uint8_t		cpu_family;
-	uint8_t		cpu_model;
-	uint8_t		cpu_extfamily;
-	uint8_t		cpu_extmodel;
-	uint64_t	msr;
-	int 		coef = 0;
-
-	do_cpuid(0, cpuid_reg);
-	cpu_vendor = cpuid_reg[1];
-
-	do_cpuid(1, cpuid_reg);
-	cpu_model = bitfield(cpuid_reg[0], 7, 4);
-	cpu_family = bitfield(cpuid_reg[0], 11, 8);
-	cpu_extmodel = bitfield(cpuid_reg[0], 19, 16);
-	cpu_extfamily = bitfield(cpuid_reg[0], 27, 20);
-
-	/* Find multiplier (by MSR) */
-	
-	if((cpu_vendor == 0x756E6547 /* Intel */) && ((cpu_family == 0x06) || (cpu_family == 0x0f)))
-	{
-		cpu_model += (cpu_extmodel << 4);
-		if ((cpu_model > 0x0d) || (cpu_model > 0x02))
-		{
-			msr = rdmsr64(IA32_PERF_STATUS);
-			div = ((msr >> 46) & 1) * 2;
-			coef = (msr >> 40) & 0x1f;
-		}
-	}
-	else if((cpu_vendor == 0x68747541 /* AMD */) && (cpu_family == 0x0f))
-		{
-			if(cpu_extfamily == 0x00 /* K8 */)
-				coef = (rdmsr64(K8_FIDVID_STATUS) & 0x3f) / 2 + 4;
-			else if(cpu_extfamily == 0x01 /* K10 */)
-			{
-				msr = rdmsr64(K10_COFVID_STATUS);
-				coef = (msr & 0x3f) + 0x10;
-				div = (2 << ((msr >> 6) & 0x07));
-			}
-		}
-
-	DBG("CPU Model: %d - CPU Family: %d - CPU Ext. Family: %d\n", cpu_model, cpu_family, cpu_extfamily);
-	return coef;
-}
-
-static uint64_t getFSBFrequency(void)
-{
-	int coef = getCPUMultiplier();
-	uint64_t cpu_freq = getCPUFrequency();
-
-	DBG("CPU Multiplier: %d", coef);
-
-	if (coef && cpu_freq)
-		if(div)
-		{
-			DBG(".%d\n", 100 / div);
-			return ((cpu_freq * div) / ((coef * div) + 1));
-		}
-		else
-		{
-			DBG("\n");
-			return (cpu_freq / coef);
-		}
+	uint64_t ret;
+	__asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
+	return ret;
+}
+
+#define MSR_IA32_PERF_STS		0x198
 
-	return (DEFAULT_FSB * 1000);
+#define bit(n)		(1ULL << (n))
+#define bitmask(h,l)	((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
+#define bitfield(x,h,l)	(((x) & bitmask(h,l)) >> l)
+
+uint64_t fsbFrequency = 0;
+
+void determineFsbFrequency()
+{
+    const char *val; // value
+    int cnt; // length of value
+
+    if(getValueForKey("fsbmhz", &val, &cnt))
+    {
+        uint32_t fsbmhz;
+        char valcpy[10];
+        bool gotvalue = (cnt < 10);
+        if(gotvalue)
+        {
+            // Force NUL-term by making a copy with strlcpy
+            strlcpy(valcpy, val, cnt+1);
+            char *endval;
+            fsbmhz = strtoul(valcpy, &endval, 10);
+            gotvalue = (valcpy != endval && *endval == '\0');
+        }
+        if(gotvalue)
+        {
+            switch(fsbmhz)
+            {
+            case 33:
+                fsbFrequency =  33333333;
+                break;
+            case 66:
+                fsbFrequency =  66666667;
+                break;
+            case 133:
+                fsbFrequency = 133333333;
+                break;
+            case 166:
+                fsbFrequency = 166666667;
+                break;
+            default:
+                printf("Strange fsbmhz=%d specified.. assuming you mean it literally.\n", fsbmhz);
+                /* Fall through */
+            case 100:
+            case 200:
+                fsbFrequency = fsbmhz * Mega;
+            }
+        }
+        else
+            fsbFrequency = 0;
+    }
+    else
+        fsbFrequency = 0;
 
+    if(fsbFrequency != 0)
+    {
+        printf("Using specified FSB Frequency %d.%06dMHz\n", (uint32_t)(fsbFrequency/Mega), (uint32_t)(fsbFrequency % Mega));
+        sleep(1);
+        return;
+    }
+    printf("Attempting to determine CPU Multiplier.  If system reboots, RDMSR 198h causes a fault.\n");
+    sleep(1);
+    uint64_t prfsts = rdmsr64(MSR_IA32_PERF_STS);
+    uint32_t tscGranularity = bitfield(prfsts, 44, 40);
+    printf("Determined CPU:FSB multiplier to be %d\n", tscGranularity);
+    if(tscGranularity == 0)
+    {
+        printf("CPU says its multiplier is 0 which makes no sense. The kernel as shipped by\n");
+        printf("Apple will not support this and will cause the machine to reboot immediately.\n");
+        printf("Press 'y' to continue or use Ctrl+Alt+Delete to reboot\n");
+        while(getc() != 'y')
+            ;
+        fsbFrequency = 0;
+        return;
+    }
+    printf("Measuring TSC frequency (e.g. CPU speed)\n");
+    uint64_t measuredTscFrequency = measure_tsc_frequency();
+    printf("CPU runs at %d.%06d MHz\n", (uint32_t)(measuredTscFrequency / Mega), (uint32_t)(measuredTscFrequency % Mega));
+    fsbFrequency = measuredTscFrequency / tscGranularity;
+    printf("BUS must therefore run at %d.%06d MHz\n", (uint32_t)(fsbFrequency / Mega), (uint32_t)(fsbFrequency % Mega));
+    sleep(1);
 }
 
 void printFrequencyInfo()
@@ -637,6 +502,10 @@
     getc();
 }
 
+/* This should be const but DT__AddProperty takes char* */
+static char FSB_Frequency_prop[] = "FSBFrequency";
+
+
 /*==========================================================================
  * SMBIOS
  */
@@ -799,19 +668,10 @@
 char const FIRMWARE_ABI_PROP[] = "firmware-abi";
 char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor";
 char const FIRMWARE_ABI_PROP_VALUE[] = "EFI32";
-char const DEVICE_PROPERTIES_PROP[] = "device-properties";
 
 void
 setupEfiDeviceTree(void)
 {
-    const char *val;
-    int cnt;
-    char hexNibble;
-    char hexByte[2];
-    uint8_t binChar;
-    uint8_t *binStr;
-    int hexStrIdx, binStrIdx, hexNibbleIdx;
-	
     Node *node;
     node = DT__FindNode("/", false);
     if (node == 0) {
@@ -827,47 +687,6 @@
     DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_PROP_VALUE), (char*)FIRMWARE_ABI_PROP_VALUE);
     DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
 
-    /* Add IODeviceTree:/efi/device-properties by decoding
-     * 'device-properties' value into binary data found in Boot.plist
-    */ 
-    if (getValueForKey(DEVICE_PROPERTIES_PROP, &val, &cnt) && cnt > 1)
-    {
-	// the resulting binary will be the half size of the input hex string
-	binStr = malloc(cnt / 2);
-	binStrIdx = 0;
-	hexNibbleIdx = 0;
-	for (hexStrIdx = 0; hexStrIdx < cnt; hexStrIdx++)
-	{
-	    hexNibble = val[hexStrIdx];
-				
-	    // ignore all chars except valid hex numbers
-	    if (hexNibble >= '0' && hexNibble <= '9' || hexNibble >= 'A' && hexNibble <= 'F' || hexNibble >= 'a' && hexNibble <= 'f')
-	    {
-		hexByte[hexNibbleIdx++] = hexNibble;
-					
-		// found both two nibbles, convert to binary
-		if (hexNibbleIdx == 2)
-		{
-		    binChar = 0;
-
-		    for (hexNibbleIdx = 0; hexNibbleIdx < sizeof(hexByte); hexNibbleIdx++)
-		    {
-			if (hexNibbleIdx > 0) binChar = binChar << 4;
-
-			if (hexByte[hexNibbleIdx] <= '9') binChar += hexByte[hexNibbleIdx] - '0';
-			else if (hexByte[hexNibbleIdx] <= 'F') binChar += hexByte[hexNibbleIdx] - ('A' - 10);
-			else if (hexByte[hexNibbleIdx] <= 'f') binChar += hexByte[hexNibbleIdx] - ('a' - 10);
-		    }
-
-		    binStr[binStrIdx++] = binChar;						
-		    hexNibbleIdx = 0;
-		}
-	    }
-	}
-
-	if (binStrIdx > 0) DT__AddProperty(node, DEVICE_PROPERTIES_PROP, binStrIdx, binStr);
-    }
-
     /* TODO: Fill in other efi properties if necessary */
 
     /* Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
@@ -889,7 +708,6 @@
     /* Now fill in the /efi/platform Node */
     Node *efiPlatformNode = DT__AddChild(node, "platform");
 
-    fsbFrequency = getFSBFrequency();
     if(fsbFrequency != 0)
         DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &fsbFrequency);
     /* NOTE WELL: If you do add FSB Frequency detection, make sure to store
@@ -912,6 +730,7 @@
 /* Entrypoint from boot.c */
 void setupFakeEfi(void)
 {
+    determineFsbFrequency();
     // Initialize the base table
     setupEfiTables();
     // Initialize the device tree
diff -Naur v51_src/i386/libsaio/fake_efi.c.OLD.c boot-132_dfe_r146/i386/libsaio/fake_efi.c.OLD.c
--- v51_src/i386/libsaio/fake_efi.c.OLD.c	2008-10-02 04:35:34.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/fake_efi.c.OLD.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,791 +0,0 @@
-/*
- * Copyright 2007 David F. Elliott.  All rights reserved.
- */
-
-#include "libsaio.h"
-#include "bootstruct.h" /* for bootArgs */
-#include <pexpert/i386/efi.h>
-#include "fake_efi.h"
-#include "efi_tables.h"
-#include "SMBIOS.h"
-
-/*
-Modern Darwin kernels require some amount of EFI because Apple machines all
-have EFI.  Modifying the kernel source to not require EFI is of course
-possible but would have to be maintained as a separate patch because it is
-unlikely that Apple wishes to add legacy support to their kernel.
-
-As you can see from the Apple-supplied code in bootstruct.c, it seems that
-the intention was clearly to modify this booter to provide EFI-like structures
-to the kernel rather than modifying the kernel to handle non-EFI stuff.  This
-makes a lot of sense from an engineering point of view as it means the kernel
-for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
-DTK systems so long as the kernel checked to ensure the boot tables were
-filled in appropriately.  Modern xnu requires a system table and a runtime
-services table and performs no checks whatsoever to ensure the pointers to
-these tables are non-NULL.  Therefore, any modern xnu kernel will page fault
-early on in the boot process if the system table pointer is zero.
-
-Even before that happens, the tsc_init function in modern xnu requires the FSB
-Frequency to be a property in the /efi/platform node of the device tree or else
-it panics the bootstrap process very early on.
-
-As of this writing, the current implementation found here is good enough
-to make the currently available xnu kernel boot without modification on a
-system with an appropriate processor.  With a minor source modification to
-the tsc_init function to remove the explicit check for Core or Core 2
-processors the kernel can be made to boot on other processors so long as
-the code can be executed by the processor and the machine contains the
-necessary hardware.
-*/
-
-
-/*==========================================================================
- * Utility function to make a device tree string from an EFI_GUID
- */
-
-static inline char * mallocStringForGuid(EFI_GUID const *pGuid)
-{
-    char *string = malloc(37);
-    efi_guid_unparse_upper(pGuid, string);
-    return string;
-}
-
-
-/*==========================================================================
- * Fake EFI implementation
- */
-
-/* Identify ourselves as the EFI firmware vendor */
-static EFI_CHAR16 const FIRMWARE_VENDOR[] = {'D','a','r','w','i','n','_','b','o','o','t', 0};
-static EFI_UINT32 const FIRMWARE_REVISION = 132; /* FIXME: Find a constant for this. */
-
-/* Just a ret instruction */
-static uint8_t const VOIDRET_INSTRUCTIONS[] = {0xc3};
-/* movl $0x80000003,%eax; ret */
-static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS[] = {0xb8, 0x03, 0x00, 0x00, 0x80, 0xc3};
-
-/* Set up space for up to 10 configuration table entries */
-#define MAX_CONFIGURATION_TABLE_ENTRIES 10
-
-/* We use the fake_efi_pages struct so that we only need to do one kernel
- * memory allocation for all needed EFI data.  Otherwise, small allocations
- * like the FIRMWARE_VENDOR string would take up an entire page.
- * NOTE WELL: Do NOT assume this struct has any particular layout within itself.
- * It is absolutely not intended to be publicly exposed anywhere
- * We say pages (plural) although right now we are well within the 1 page size
- * and probably will stay that way.
- */
-struct fake_efi_pages
-{
-    EFI_SYSTEM_TABLE efiSystemTable;
-    EFI_RUNTIME_SERVICES efiRuntimeServices;
-    EFI_CONFIGURATION_TABLE efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
-    EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
-    uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
-    uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS)/sizeof(uint8_t)];
-};
-
-EFI_SYSTEM_TABLE *gST = NULL;
-Node *gEfiConfigurationTableNode = NULL;
-
-static EFI_STATUS addConfigurationTable(EFI_GUID const *pGuid, void *table, char const *alias)
-{
-    EFI_UINTN i = gST->NumberOfTableEntries;
-    /* We only do adds, not modifications and deletes like InstallConfigurationTable */
-    if(i >= MAX_CONFIGURATION_TABLE_ENTRIES)
-        stop("Ran out of space for configuration tables.  Increase the reserved size in the code.\n");
-
-    if(pGuid == NULL)
-        return EFI_INVALID_PARAMETER;
-
-    if(table != NULL)
-    {
-        gST->ConfigurationTable[i].VendorGuid = *pGuid;
-        gST->ConfigurationTable[i].VendorTable = table;
-
-        ++gST->NumberOfTableEntries;
-
-        Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
-        /* Use the pointer to the GUID we just stuffed into the system table */
-        DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID),&gST->ConfigurationTable[i].VendorGuid);
-	/* The "table" property is the 32-bit (in our implementation) physical address of the table */
-        DT__AddProperty(tableNode, "table", sizeof(void*), &gST->ConfigurationTable[i].VendorTable);
-        /* Assume the alias pointer is a global or static piece of data */
-        if(alias != NULL)
-            DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char*)alias);
-        return EFI_SUCCESS;
-    }
-    return EFI_UNSUPPORTED;
-}
-
-static inline void fixupEfiSystemTableCRC32(EFI_SYSTEM_TABLE *efiSystemTable)
-{
-    efiSystemTable->Hdr.CRC32 = 0;
-    efiSystemTable->Hdr.CRC32 = crc32(0L, efiSystemTable, efiSystemTable->Hdr.HeaderSize);
-}
-
-/*
-What we do here is simply allocate a fake EFI system table and a fake EFI
-runtime services table.
-
-Because we build against modern headers with kBootArgsRevision 4 we
-also take care to set efiMode = 32.
-*/
-void
-setupEfiTables(void)
-{
-    struct fake_efi_pages *fakeEfiPages= (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
-
-    /* Zero out all the tables in case fields are added later */
-    bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
-
-    /* --------------------------------------------------------------------
-     * Initialize some machine code that will return EFI_UNSUPPORTED for
-     * functions returning int and simply return for void functions.
-     */
-    memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
-    memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS, sizeof(UNSUPPORTEDRET_INSTRUCTIONS));
-
-    /* -------------------------------------------------------------------- */
-    /* System table */
-    EFI_SYSTEM_TABLE *efiSystemTable = gST = &fakeEfiPages->efiSystemTable;
-    efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
-    efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
-    efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE);
-    efiSystemTable->Hdr.CRC32 = 0; /* Initialize to zero and then do CRC32 */
-    efiSystemTable->Hdr.Reserved = 0;
-
-    efiSystemTable->FirmwareVendor = fakeEfiPages->firmwareVendor;
-    memcpy(efiSystemTable->FirmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
-    efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
-
-    /* XXX: We may need to have basic implementations of ConIn/ConOut/StdErr */
-    /* The EFI spec states that all handles are invalid after boot services have been
-     * exited so we can probably get by with leaving the handles as zero. */
-    efiSystemTable->ConsoleInHandle = 0;
-    efiSystemTable->ConIn = 0;
-
-    efiSystemTable->ConsoleOutHandle = 0;
-    efiSystemTable->ConOut = 0;
-
-    efiSystemTable->StandardErrorHandle = 0;
-    efiSystemTable->StdErr = 0;
-
-    efiSystemTable->RuntimeServices = &fakeEfiPages->efiRuntimeServices;
-    /* According to the EFI spec, BootServices aren't valid after the
-     * boot process is exited so we can probably do without it.
-     * Apple didn't provide a definition for it in pexpert/i386/efi.h
-     * so I'm guessing they don't use it.
-    */
-    efiSystemTable->BootServices = 0;
-
-    efiSystemTable->NumberOfTableEntries = 0;
-    efiSystemTable->ConfigurationTable = fakeEfiPages->efiConfigurationTable;
-
-
-    /* We're done.  Now CRC32 the thing so the kernel will accept it */
-    fixupEfiSystemTableCRC32(efiSystemTable);
-
-    /* -------------------------------------------------------------------- */
-    /* Runtime services */
-    EFI_RUNTIME_SERVICES *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
-    efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
-    efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
-    efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES);
-    efiRuntimeServices->Hdr.CRC32 = 0;
-    efiRuntimeServices->Hdr.Reserved = 0;
-
-    /* There are a number of function pointers in the efiRuntimeServices table.
-     * These are the Foundation (e.g. core) services and are expected to be present on
-     * all EFI-compliant machines.  Some kernel extensions (notably AppleEFIRuntime)
-     * will call these without checking to see if they are null.
-     *
-     * We don't really feel like doing an EFI implementation in the bootloader
-     * but it is nice if we can at least prevent a complete crash by
-     * at least providing some sort of implementation until one can be provided
-     * nicely in a kext.
-     */
-    void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
-    void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
-    efiRuntimeServices->GetTime = (void*)unsupportedret_fp;
-    efiRuntimeServices->SetTime = (void*)unsupportedret_fp;
-    efiRuntimeServices->GetWakeupTime = (void*)unsupportedret_fp;
-    efiRuntimeServices->SetWakeupTime = (void*)unsupportedret_fp;
-    efiRuntimeServices->SetVirtualAddressMap = (void*)unsupportedret_fp;
-    efiRuntimeServices->ConvertPointer = (void*)unsupportedret_fp;
-    efiRuntimeServices->GetVariable = (void*)unsupportedret_fp;
-    efiRuntimeServices->GetNextVariableName = (void*)unsupportedret_fp;
-    efiRuntimeServices->SetVariable = (void*)unsupportedret_fp;
-    efiRuntimeServices->GetNextHighMonotonicCount = (void*)unsupportedret_fp;
-    efiRuntimeServices->ResetSystem = (void*)voidret_fp;
-
-    /* We're done.  Now CRC32 the thing so the kernel will accept it */
-    efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
-
-
-    /* -------------------------------------------------------------------- */
-    /* Finish filling in the rest of the boot args that we need. */
-    bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
-    bootArgs->efiMode = kBootArgsEfiMode32;
-
-    /* The bootArgs structure as a whole is bzero'd so we don't need to fill in
-     * things like efiRuntimeServices* and what not.
-     *
-     * In fact, the only code that seems to use that is the hibernate code so it
-     * knows not to save the pages.  It even checks to make sure its nonzero.
-     */
-}
-
-/*
-In addition to the EFI tables there is also the EFI device tree node.
-In particular, we need /efi/platform to have an FSBFrequency key. Without it,
-the tsc_init function will panic very early on in kernel startup, before
-the console is available.
-*/
-
-/* Decimal powers: */
-#define kilo (1000ULL)
-#define Mega (kilo * kilo)
-#define Giga (kilo * Mega)
-#define Tera (kilo * Giga)
-#define Peta (kilo * Tera)
-
-/*==========================================================================
- * FSB Frequency detection
- */
-// DFE: rdtsc64 from xnu (obvious implementation)
-static inline uint64_t rdtsc64(void)
-{
-    uint64_t ret;
-    __asm__ volatile("rdtsc" : "=A" (ret));
-    return ret;
-}
-
-// DFE: enable_PIT2 and disable_PIT2 come from older xnu
-
-/*
- * Enable or disable timer 2.
- * Port 0x61 controls timer 2:
- *   bit 0 gates the clock,
- *   bit 1 gates output to speaker.
- */
-inline static void
-enable_PIT2(void)
-{
-    /* Enable gate, disable speaker */
-    __asm__ volatile(
-        " inb   $0x61,%%al      \n\t"
-        " and   $0xFC,%%al       \n\t"  /* & ~0x03 */
-        " or    $1,%%al         \n\t"
-        " outb  %%al,$0x61      \n\t"
-        : : : "%al" );
-}
-
-inline static void
-disable_PIT2(void)
-{
-    /* Disable gate and output to speaker */
-    __asm__ volatile(
-        " inb   $0x61,%%al      \n\t"
-        " and   $0xFC,%%al      \n\t"	/* & ~0x03 */
-        " outb  %%al,$0x61      \n\t"
-        : : : "%al" );
-}
-
-// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
-// roughly based on Linux code
-
-/* Set the 8254 channel 2 to mode 0 with the specified value.
-   In mode 0, the counter will initially set its gate low when the
-   timer expires.  For this to be useful, you ought to set it high
-   before calling this function.  The enable_PIT2 function does this.
- */
-static inline void set_PIT2_mode0(uint16_t value)
-{
-    __asm__ volatile(
-        " movb  $0xB0,%%al      \n\t"
-        " outb	%%al,$0x43	\n\t"
-        " movb	%%dl,%%al	\n\t"
-        " outb	%%al,$0x42	\n\t"
-        " movb	%%dh,%%al	\n\t"
-        " outb	%%al,$0x42"
-        : : "d"(value) /*: no clobber */ );
-}
-
-/* Returns the number of times the loop ran before the PIT2 signaled */
-static inline unsigned long poll_PIT2_gate(void)
-{
-    unsigned long count = 0;
-    unsigned char nmi_sc_val;
-    do {
-        ++count;
-        __asm__ volatile(
-            "inb	$0x61,%0"
-        : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
-    } while( (nmi_sc_val & 0x20) == 0);
-    return count;
-}
-
-// DFE: This constant comes from older xnu:
-#define CLKNUM		1193182		/* formerly 1193167 */
-
-// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM
-#define CALIBRATE_TIME_MSEC 30 /* 30 msecs */
-#define CALIBRATE_LATCH	\
-	((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)
-
-/*
- * Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
- */
-uint64_t measure_tsc_frequency(void);
-uint64_t measure_tsc_frequency(void)
-{
-    uint64_t tscStart;
-    uint64_t tscEnd;
-    uint64_t tscDelta = 0xffffffffffffffffULL;
-    unsigned long pollCount;
-    uint64_t retval = 0;
-    int i;
-
-    /* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
-     * counter 2.  We run this loop 3 times to make sure the cache
-     * is hot and we take the minimum delta from all of the runs.
-     * That is to say that we're biased towards measuring the minimum
-     * number of TSC ticks that occur while waiting for the timer to
-     * expire.  That theoretically helps avoid inconsistencies when
-     * running under a VM if the TSC is not virtualized and the host
-     * steals time.  The TSC is normally virtualized for VMware.
-     */
-    for(i = 0; i < 3; ++i)
-    {
-        enable_PIT2();
-        set_PIT2_mode0(CALIBRATE_LATCH);
-        tscStart = rdtsc64();
-        pollCount = poll_PIT2_gate();
-        tscEnd = rdtsc64();
-        /* The poll loop must have run at least a few times for accuracy */
-        if(pollCount <= 1)
-            continue;
-        /* The TSC must increment at LEAST once every millisecond.  We
-         * should have waited exactly 30 msec so the TSC delta should
-         * be >= 30.  Anything less and the processor is way too slow.
-         */
-        if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)
-            continue;
-        // tscDelta = min(tscDelta, (tscEnd - tscStart))
-        if( (tscEnd - tscStart) < tscDelta )
-            tscDelta = tscEnd - tscStart;
-    }
-    /* tscDelta is now the least number of TSC ticks the processor made in
-     * a timespan of 0.03 s (e.g. 30 milliseconds)
-     * Linux thus divides by 30 which gives the answer in kiloHertz because
-     * 1 / ms = kHz.  But we're xnu and most of the rest of the code uses
-     * Hz so we need to convert our milliseconds to seconds.  Since we're
-     * dividing by the milliseconds, we simply multiply by 1000.
-     */
-
-    /* Unlike linux, we're not limited to 32-bit, but we do need to take care
-     * that we're going to multiply by 1000 first so we do need at least some
-     * arithmetic headroom.  For now, 32-bit should be enough.
-     * Also unlike Linux, our compiler can do 64-bit integer arithmetic.
-     */
-    if(tscDelta > (1ULL<<32))
-        retval = 0;
-    else
-    {
-        retval = tscDelta * 1000 / 30;
-    }
-    disable_PIT2();
-    return retval;
-}
-
-static inline uint64_t rdmsr64(uint32_t msr)
-{
-	uint64_t ret;
-	__asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
-	return ret;
-}
-
-#define MSR_IA32_PERF_STS		0x198
-
-#define bit(n)		(1ULL << (n))
-#define bitmask(h,l)	((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
-#define bitfield(x,h,l)	(((x) & bitmask(h,l)) >> l)
-
-uint64_t fsbFrequency = 0;
-
-void determineFsbFrequency()
-{
-    const char *val; // value
-    int cnt; // length of value
-
-    if(getValueForKey("fsbmhz", &val, &cnt))
-    {
-        uint32_t fsbmhz;
-        char valcpy[10];
-        bool gotvalue = (cnt < 10);
-        if(gotvalue)
-        {
-            // Force NUL-term by making a copy with strlcpy
-            strlcpy(valcpy, val, cnt+1);
-            char *endval;
-            fsbmhz = strtoul(valcpy, &endval, 10);
-            gotvalue = (valcpy != endval && *endval == '\0');
-        }
-        if(gotvalue)
-        {
-            switch(fsbmhz)
-            {
-            case 33:
-                fsbFrequency =  33333333;
-                break;
-            case 66:
-                fsbFrequency =  66666667;
-                break;
-            case 133:
-                fsbFrequency = 133333333;
-                break;
-            case 166:
-                fsbFrequency = 166666667;
-                break;
-            default:
-                printf("Strange fsbmhz=%d specified.. assuming you mean it literally.\n", fsbmhz);
-                /* Fall through */
-            case 100:
-            case 200:
-                fsbFrequency = fsbmhz * Mega;
-            }
-        }
-        else
-            fsbFrequency = 0;
-    }
-    else
-        fsbFrequency = 0;
-
-    if(fsbFrequency != 0)
-    {
-        printf("Using specified FSB Frequency %d.%06dMHz\n", (uint32_t)(fsbFrequency/Mega), (uint32_t)(fsbFrequency % Mega));
-        //sleep(1);
-        return;
-    }
-    printf("Attempting to determine CPU Multiplier.  If system reboots, RDMSR 198h causes a fault.\n");
-    //sleep(1);
-    uint64_t prfsts = rdmsr64(MSR_IA32_PERF_STS);
-    uint32_t tscGranularity = bitfield(prfsts, 44, 40);
-    printf("Determined CPU:FSB multiplier to be %d\n", tscGranularity);
-    if(tscGranularity == 0)
-    {
-        printf("CPU says its multiplier is 0 which makes no sense. The kernel as shipped by\n");
-        printf("Apple will not support this and will cause the machine to reboot immediately.\n");
-        printf("Press 'y' to continue or use Ctrl+Alt+Delete to reboot\n");
-        while(getc() != 'y')
-            ;
-        fsbFrequency = 0;
-        return;
-    }
-    printf("Measuring TSC frequency (e.g. CPU speed)\n");
-    uint64_t measuredTscFrequency = measure_tsc_frequency();
-    printf("CPU runs at %d.%06d MHz\n", (uint32_t)(measuredTscFrequency / Mega), (uint32_t)(measuredTscFrequency % Mega));
-    fsbFrequency = measuredTscFrequency / tscGranularity;
-    printf("BUS must therefore run at %d.%06d MHz\n", (uint32_t)(fsbFrequency / Mega), (uint32_t)(fsbFrequency % Mega));
-    //sleep(1);
-}
-
-void printFrequencyInfo()
-{
-    printf("\n");
-    uint64_t measuredTscFrequency = measure_tsc_frequency();
-    printf("CPU runs at %d.%06d MHz\n", (uint32_t)(measuredTscFrequency / Mega), (uint32_t)(measuredTscFrequency % Mega));
-    printf("\n");
-    printf("(Press a key to continue...)");
-    getc();
-}
-
-/* This should be const but DT__AddProperty takes char* */
-static char FSB_Frequency_prop[] = "FSBFrequency";
-
-
-/*==========================================================================
- * SMBIOS
- */
-
-/* From Foundation/Efi/Guid/Smbios/SmBios.h */
-/* Modified to wrap Data4 array init with {} */
-#define EFI_SMBIOS_TABLE_GUID \
-  { \
-    0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} \
-  }
-
-/* From Foundation/Efi/Guid/Smbios/SmBios.c */
-EFI_GUID const  gEfiSmbiosTableGuid = EFI_SMBIOS_TABLE_GUID;
-
-#define SMBIOS_RANGE_START      0x000F0000
-#define SMBIOS_RANGE_END        0x000FFFFF
-
-/* '_SM_' in little endian: */
-#define SMBIOS_ANCHOR_UINT32_LE 0x5f4d535f
-
-static inline void* getAddressOfSmbiosTable()
-{
-    /* First see if we can even find the damn SMBIOS table
-     * The logic here is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking
-     * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_").
-     */
-    void *smbios_addr = (void*)SMBIOS_RANGE_START;
-    for(; (smbios_addr <= (void*)SMBIOS_RANGE_END) && (*(uint32_t*)smbios_addr != SMBIOS_ANCHOR_UINT32_LE); smbios_addr += 16)
-        ;
-    if(smbios_addr <= (void*)SMBIOS_RANGE_END)
-    {
-        /* NOTE: The specification does not specifically state what to do in the event of finding an
-         * SMBIOS anchor on an invalid table.  It might be better to move this code into the for loop
-         * so that searching can continue.
-         */
-        uint8_t csum = checksum8(smbios_addr, sizeof(struct SMBEntryPoint));
-        /* The table already contains the checksum so we merely need to see if its checksum is now zero. */
-        if(csum != 0)
-        {
-            printf("Found SMBIOS anchor but bad table checksum.  Assuming no SMBIOS.\n");
-            sleep(5);
-            smbios_addr = 0;
-        }
-    }
-    else
-    {
-        /* If this happens, it's possible that a PnP BIOS call can be done to retrieve the address of the table.
-         * The latest versions of the spec state that modern programs should not even attempt to do this. */
-        printf("Unable to find SMBIOS table.\n");
-        sleep(5);
-        smbios_addr = 0;
-    }
-    return smbios_addr;
-}
-
-
-/*==========================================================================
- * ACPI
- */
-
-#define EFI_ACPI_TABLE_GUID \
-  { \
-    0xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
-  }
-
-#define EFI_ACPI_20_TABLE_GUID \
-  { \
-    0x8868e871, 0xe4f1, 0x11d3, { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
-  }
-
-// NOTE: ACPI 3.0 uses same GUID as ACPI 2.0
-
-EFI_GUID  gEfiAcpiTableGuid = EFI_ACPI_TABLE_GUID;
-
-EFI_GUID  gEfiAcpi20TableGuid = EFI_ACPI_20_TABLE_GUID;
-
-#define ACPI_RANGE_START    (0x0E0000)
-#define ACPI_RANGE_END      (0x0FFFFF)
-
-#define UINT64_LE_FROM_CHARS(a,b,c,d,e,f,g,h) \
-    (   ((uint64_t)h << 56) \
-    |   ((uint64_t)g << 48) \
-    |   ((uint64_t)f << 40) \
-    |   ((uint64_t)e << 32) \
-    |   ((uint64_t)d << 24) \
-    |   ((uint64_t)c << 16) \
-    |   ((uint64_t)b <<  8) \
-    |   ((uint64_t)a <<  0) \
-    )
-
-#define ACPI_SIGNATURE_UINT64_LE UINT64_LE_FROM_CHARS('R','S','D',' ','P','T','R',' ')
-
-/* Per ACPI 3.0a spec */
-struct acpi_2_rsdp {
-    char            Signature[8];
-    uint8_t         Checksum;
-    char            OEMID[6];
-    uint8_t         Revision;
-    uint32_t        RsdtAddress;
-    uint32_t        Length;
-    uint64_t        XsdtAddress;
-    uint8_t         ExtendedChecksum;
-    char            Reserved[3];
-} __attribute__((packed));
-
-/* Gets the ACPI 1.0 RSDP address */
-static void* getAddressOfAcpiTable()
-{
-    /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
-
-    void *acpi_addr = (void*)ACPI_RANGE_START;
-    for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
-    {
-        if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
-        {
-            uint8_t csum = checksum8(acpi_addr, 20);
-            if(csum == 0)
-            {
-                // Only return the table if it is a true version 1.0 table (Revision 0)
-                if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
-                    return acpi_addr;
-            }
-        }
-    }
-    return NULL;
-}
-
-/* Gets the ACPI 2.0 RSDP address */
-static void* getAddressOfAcpi20Table()
-{
-    /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
-
-    void *acpi_addr = (void*)ACPI_RANGE_START;
-    for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
-    {
-        if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
-        {
-            uint8_t csum = checksum8(acpi_addr, 20);
-            /* Only assume this is a 2.0 or better table if the revision is greater than 0
-             * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
-             * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
-             */
-            if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
-            {
-                uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
-                if(csum2 == 0)
-                    return acpi_addr;
-            }
-        }
-    }
-    return NULL;
-}
-
-
-/*==========================================================================
- * Fake EFI implementation
- */
-
-char const FIRMWARE_REVISION_PROP[] = "firmware-revision";
-char const FIRMWARE_ABI_PROP[] = "firmware-abi";
-char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor";
-char const FIRMWARE_ABI_PROP_VALUE[] = "EFI32";
-char const DEVICE_PROPERTIES_PROP[] = "device-properties";
-
-void
-setupEfiDeviceTree(void)
-{
-    const char *val;
-    int cnt;
-    char hexNibble;
-    char hexByte[2];
-    uint8_t binChar;
-    uint8_t *binStr;
-    int hexStrIdx, binStrIdx, hexNibbleIdx;
-	
-    Node *node;
-    node = DT__FindNode("/", false);
-    if (node == 0) {
-        stop("Couldn't get root node");
-    }
-    /* We could also just do DT__FindNode("/efi/platform", true)
-     * But I think eventually we want to fill stuff in the efi node
-     * too so we might as well create it so we have a pointer for it too.
-    */
-    node = DT__AddChild(node, "efi");
-
-    DT__AddProperty(node, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32*)&FIRMWARE_REVISION);
-    DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_PROP_VALUE), (char*)FIRMWARE_ABI_PROP_VALUE);
-    DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
-
-    /* Add IODeviceTree:/efi/device-properties by decoding
-     * 'device-properties' value into binary data found in Boot.plist
-    */ 
-    if (getValueForKey(DEVICE_PROPERTIES_PROP, &val, &cnt) && cnt > 1)
-    {
-	// the resulting binary will be the half size of the input hex string
-	binStr = malloc(cnt / 2);
-	binStrIdx = 0;
-	hexNibbleIdx = 0;
-	for (hexStrIdx = 0; hexStrIdx < cnt; hexStrIdx++)
-	{
-	    hexNibble = val[hexStrIdx];
-				
-	    // ignore all chars except valid hex numbers
-	    if (hexNibble >= '0' && hexNibble <= '9' || hexNibble >= 'A' && hexNibble <= 'F' || hexNibble >= 'a' && hexNibble <= 'f')
-	    {
-		hexByte[hexNibbleIdx++] = hexNibble;
-					
-		// found both two nibbles, convert to binary
-		if (hexNibbleIdx == 2)
-		{
-		    binChar = 0;
-
-		    for (hexNibbleIdx = 0; hexNibbleIdx < sizeof(hexByte); hexNibbleIdx++)
-		    {
-			if (hexNibbleIdx > 0) binChar = binChar << 4;
-
-			if (hexByte[hexNibbleIdx] <= '9') binChar += hexByte[hexNibbleIdx] - '0';
-			else if (hexByte[hexNibbleIdx] <= 'F') binChar += hexByte[hexNibbleIdx] - ('A' - 10);
-			else if (hexByte[hexNibbleIdx] <= 'f') binChar += hexByte[hexNibbleIdx] - ('a' - 10);
-		    }
-
-		    binStr[binStrIdx++] = binChar;						
-		    hexNibbleIdx = 0;
-		}
-	    }
-	}
-
-	if (binStrIdx > 0) DT__AddProperty(node, DEVICE_PROPERTIES_PROP, binStrIdx, binStr);
-    }
-
-    /* TODO: Fill in other efi properties if necessary */
-
-    /* Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
-     * is set up.  That is, name and table properties */
-    Node *runtimeServicesNode = DT__AddChild(node, "runtime-services");
-
-    /* The value of the table property is the 32-bit physical address for the RuntimeServices table.
-     * Sice the EFI system table already has a pointer to it, we simply use the address of that pointer
-     * for the pointer to the property data.  Warning.. DT finalization calls free on that but we're not
-     * the only thing to use a non-malloc'd pointer for something in the DT
-     */
-    DT__AddProperty(runtimeServicesNode, "table", sizeof(void *), &gST->RuntimeServices);
-
-    /* Set up the /efi/configuration-table node which will eventually have several child nodes for
-     * all of the configuration tables needed by various kernel extensions.
-     */
-    gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table");
-
-    /* Now fill in the /efi/platform Node */
-    Node *efiPlatformNode = DT__AddChild(node, "platform");
-
-    if(fsbFrequency != 0)
-        DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &fsbFrequency);
-    /* NOTE WELL: If you do add FSB Frequency detection, make sure to store
-     * the value in the fsbFrequency global and not an malloc'd pointer
-     * because the DT_AddProperty function does not copy its args.
-     */
-}
-
-/* Installs all the needed configuration table entries */
-void setupEfiConfigurationTable()
-{
-    addConfigurationTable(&gEfiSmbiosTableGuid, getAddressOfSmbiosTable(), NULL);
-    addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
-    addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
-
-    // We've obviously changed the count.. so fix up the CRC32
-    fixupEfiSystemTableCRC32(gST);
-}
-
-/* Entrypoint from boot.c */
-void setupFakeEfi(void)
-{
-    determineFsbFrequency();
-    // Initialize the base table
-    setupEfiTables();
-    // Initialize the device tree
-    setupEfiDeviceTree();
-    // Add configuration table entries to both the services table and the device tree
-    setupEfiConfigurationTable();
-}
-
diff -Naur v51_src/i386/libsaio/saio_internal.h boot-132_dfe_r146/i386/libsaio/saio_internal.h
--- v51_src/i386/libsaio/saio_internal.h	2008-10-06 02:54:18.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/saio_internal.h	2008-06-29 05:51:25.000000000 +0200
@@ -44,7 +44,7 @@
 extern int    bgetc(void);
 extern int    biosread(int dev, int cyl, int head, int sec, int num);
 extern int    ebiosread(int dev, long sec, int count);
-//extern int    ebioswrite(int dev, long sec, int count);
+extern int    ebioswrite(int dev, long sec, int count);
 extern int    get_drive_info(int drive, struct driveInfo *dp);
 extern int ebiosEjectMedia(int biosdev);
 extern void   putc(int ch);
@@ -103,7 +103,7 @@
 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    rawDiskWrite(BVRef bvr, unsigned int secno, void *buffer, unsigned int len);
 extern int    readBootSector(int biosdev, unsigned int secno, void *buffer);
 extern void   turnOffFloppy(void);
 
diff -Naur v51_src/i386/libsaio/stringTable.c boot-132_dfe_r146/i386/libsaio/stringTable.c
--- v51_src/i386/libsaio/stringTable.c	2008-10-02 04:24:42.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/stringTable.c	2007-06-27 18:02:45.000000000 +0200
@@ -481,8 +481,6 @@
 #define LP '('
 #define RP ')'
 
-#define EFI_PART_CONFIG_DIR1 "bt(0,0)/Library/Preferences/SystemConfiguration"
-#define EFI_PART_CONFIG_DIR2 "bt(0,0)"
 #define SYSTEM_CONFIG_DIR "/Library/Preferences/SystemConfiguration"
 #define SYSTEM_CONFIG_FILE "/com.apple.Boot.plist"
 #define LRE_CONFIG_FILE "/com.apple.lre.Boot.plist"
@@ -597,20 +595,6 @@
         strcat(bp, LRE_CONFIG_FILE);
         ret = loadConfigFile(bp);
 
-		if (ret < 0) {
-			/* If not found, try to load from EFI partition in Library/Preferences/SystemConfiguration */
-			strcpy(bp, EFI_PART_CONFIG_DIR1);
-			strcat(bp, SYSTEM_CONFIG_FILE);
-			ret = loadConfigFile(bp);
-		}
-
-		if (ret < 0) {
-			/* If not found, try to load from EFI partition root */
-			strcpy(bp, EFI_PART_CONFIG_DIR2);
-			strcat(bp, SYSTEM_CONFIG_FILE);
-			ret = loadConfigFile(bp);
-		}
-		
         if (ret < 0) {
             /* If not found, try default file */
             strcpy(bp, systemConfigDir());
diff -Naur v51_src/i386/libsaio/sys.c boot-132_dfe_r146/i386/libsaio/sys.c
--- v51_src/i386/libsaio/sys.c	2008-10-02 03:47:24.000000000 +0200
+++ boot-132_dfe_r146/i386/libsaio/sys.c	2008-06-28 22:48:39.000000000 +0200
@@ -89,7 +89,6 @@
     { "fd", 0x00, kBIOSDevTypeFloppy    },  /* DEV_FD */
     { "en", 0xE0, kBIOSDevTypeNetwork   },  /* DEV_EN */
     { "rd", 0x100, kBIOSDevTypeHardDrive },
-    { "bt", 0x101, kBIOSDevTypeHardDrive }, // turbo - type for booter partition
     { 0, 0 }
 };
 
@@ -102,8 +101,6 @@
 
 void * gFSLoadAddress = 0;
 
-extern BVRef gBIOSBootVolume; // turbo - original partition
-
 //static BVRef getBootVolumeRef( const char * path, const char ** outPath );
 static BVRef newBootVolumeRef( int biosdev, int partno );
 
@@ -781,8 +778,6 @@
         if (*cp == RP) cp++;
         
         biosdev = dp->biosdev + unit;
-        // turbo
-        if (biosdev == 0x101) bvr = gBIOSBootVolume; else
         bvr = newBootVolumeRef(biosdev, part);
 
         if(bvr == NULL)