# Makefile for kernel booter
-# CFLAGS = -O $(MORECPP) -arch i386 -g -munaligned-text
+# CFLAGS = -O $(MORECPP) -arch i386 -g
DEFINES=
CONFIG = hd
LIBDIR = libsa
# Machine-independent code
#
-#CFLAGS = -O $(MORECPP) -arch i386 -g -munaligned-text
+#CFLAGS = -O $(MORECPP) -arch i386 -g
DEFINES=
CONFIG = hd
LIBDIR = libsa
INSTALL_MI_DIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/machdep/machine
DEBUG = -O
-CFLAGS = $(DEBUG) $(MORECPP) -arch i386 -g -Wmost -Wno-precomp -munaligned-text
+CFLAGS = $(DEBUG) $(MORECPP) -arch i386 -g -Wmost -Wno-precomp
DEFINES=
CONFIG = hd
INC = -I. -I$(SYMROOT) -I$(UTILDIR)
#define DRIVER_PRIVATE
#import "sys/types.h"
-#import <bsd/dev/disk.h>
-#import <bsd/dev/i386/disk.h>
+#import <dev/disk.h>
+#import <dev/i386/disk.h>
#import "libsaio.h"
#import "memory.h"
* All rights reserved.
*/
-#import <bsd/sys/types.h>
-#import <bsd/sys/param.h>
-#import <bsd/sys/vnode.h>
-#import <bsd/ufs/fsdir.h>
+#import <sys/types.h>
+#import <sys/param.h>
+#import <sys/vnode.h>
+#import <ufs/fsdir.h>
#import <architecture/byte_order.h>
#import "ufs_byteorder.h"
#import "libsaio.h"
* 8 Jul 1992 Brian Pinkerton at NeXT
* Created.
*/
-#import <bsd/sys/disktab.h>
-#import <bsd/sys/vnode.h>
-#import <bsd/sys/buf.h>
-#import <bsd/dev/disk.h>
-#import <bsd/ufs/fs.h>
-#import <bsd/ufs/inode.h>
+#import <sys/disktab.h>
+#import <sys/vnode.h>
+#import <sys/buf.h>
+#import <dev/disk.h>
+#import <ufs/fs.h>
+#import <ufs/inode.h>
void byte_swap_ints(int *array, int count);
void byte_swap_shorts(short *array, int count);
INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone
DEBUG = -O
-CFLAGS = $(DEBUG) $(MORECPP) $(RC_CFLAGS) -g -Wmost -Wno-precomp -traditional-cpp
+CFLAGS = $(DEBUG) $(MORECPP) $(RC_CFLAGS) -g -Wmost -Werror
DEFINES=
CONFIG = hd
INC = -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR)
* @APPLE_LICENSE_HEADER_END@
*/
#import <stdio.h>
+#import <stdlib.h>
#import <mach/mach.h>
#import <mach/mach_error.h>
#import <mach/mach_traps.h>
exit(1);
}
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
char *infile = NULL, *outfile = NULL;
int compress = 0;
int verbose = 0;
- FILE *inf, *outf;
+ FILE *inf, *outf = NULL;
unsigned char *inbuf, *outbuf;
unsigned long length, total;
kern_return_t ret;
}
fseek(inf,0,2); length = ftell(inf); rewind(inf);
- if ((ret = map_fd(fileno(inf), 0, &inbuf, TRUE, length)) != KERN_SUCCESS) {
+ if ((ret = map_fd(fileno(inf), 0, (vm_address_t *)&inbuf, TRUE, length)) != KERN_SUCCESS) {
mach_error("map_fd", ret);
exit(1);
}
if (verbose)
fprintf(stderr, "%ld %ld\nCompression ratio: %f\n", length, total, total/(1.0*length));
fclose(inf);
- vm_deallocate(mach_task_self(), inbuf, length);
+ vm_deallocate(mach_task_self(), (vm_address_t)inbuf, length);
fclose(outf);
} else {
unsigned char *ptr;
}
}
fseek(inf,0,2); length = ftell(inf); rewind(inf);
- if ((ret = map_fd(fileno(inf), 0, &inbuf, TRUE, length)) != KERN_SUCCESS) {
+ if ((ret = map_fd(fileno(inf), 0, (vm_address_t *)&inbuf, TRUE, length)) != KERN_SUCCESS) {
mach_error("map_fd", ret);
exit(1);
}
if (verbose)
fprintf(stderr, "%ld %ld\nCompression ratio: %f\n", length, total, total/(1.0*length));
fclose(inf);
- vm_deallocate(mach_task_self(), inbuf, length);
+ vm_deallocate(mach_task_self(), (vm_address_t)inbuf, length);
fclose(outf);
}
exit(0);
)
/* Returns actual number of bytes emitted as compressed stream 'out.' */
{
- unsigned int c, ct, j, jmatch, jabove, match;
- unsigned int data[32], version;
- unsigned int word, token, tokenct, total;
+ unsigned int c, ct, j, jmatch = 0, jabove, match;
+ unsigned int data[32];
+ unsigned int word, token, tokenct;
unsigned char *outorigin = out;
/* First, put version number into stream. */
unsigned int c, j, k, jmatch, jabove;
unsigned int length, even_length, word, token, version;
unsigned char *outorigin = out;
- int *a, *b;
version = *in++;
version = (version<<8) | (*in++);
# Makefile for i386 boot program
# define FLOPPY and SMALL using DEFINES macro as necessary
-CFLAGS = -O $(MORECPP) -arch i386 -g -mi386:unaligned-text -static
+CFLAGS = -O $(MORECPP) -arch i386 -g -static
DEFINES=
CONFIG = hd
LIBDIR = libsa
; responsibility is to locate the booter partition, load the
; booter into memory, and jump to the booter's entry point.
; The booter partition can be a primary or a logical partition.
-; But the booter partition must reside within the 8GB limit
-; imposed by CHS addressing + translation.
;
; This boot loader can be placed at any of the following places:
-; * Master Boot Record (MBR)
-; * Boot sector of an extended partition
-; * Boot sector of a primary partition
-; * Boot sector of a logical partition
+; 1. Master Boot Record (MBR)
+; 2. Boot sector of an extended partition
+; 3. Boot sector of a primary partition
+; 4. Boot sector of a logical partition
;
; In order to coexist with a fdisk partition table (64 bytes), and
; leave room for a two byte signature (0xAA55) in the end, boot0 is
; restricted to 446 bytes (512 - 64 - 2). If boot0 did not have to
-; live in the MBR, then we would have 510 bytes to play with.
+; live in the MBR, then we would have 510 bytes to work with.
;
-; boot0 is always loaded by the BIOS or another first level booter
-; to 0:7C00h.
+; boot0 is always loaded by the BIOS or another booter to 0:7C00h.
;
; This code is written for the NASM assembler.
; nasm boot0.s -o boot0
-;--------------------------------------------------------------------------
-; Constants.
-DEBUG EQU 0 ; enable debugging output
+;
+; Set to 1 to enable obscure debug messages.
+;
+DEBUG EQU 0
+
+;
+; Set to 1 to support loading the booter (boot2) from a
+; logical partition.
+;
+EXT_PART_SUPPORT EQU 1
+
+;
+; Various constants.
+;
+kBoot0Segment EQU 0x0000
+kBoot0Stack EQU 0xFFF0 ; boot0 stack pointer
+kBoot0LoadAddr EQU 0x7C00 ; boot0 load address
+kBoot0RelocAddr EQU 0xE000 ; boot0 relocated address
+
+kMBRBuffer EQU 0x1000 ; MBR buffer address
+kExtBuffer EQU 0x1200 ; EXT boot block buffer address
-BOOTSEG EQU 0x0 ; our sole segment
-BOOTSP EQU 0xFFF0 ; stack pointer
-BOOTLOAD EQU 0x7C00 ; booter load address
-BOOTRELOC EQU 0xE000 ; booter is relocated here
-BOOTSIG EQU 0xAA55 ; booter signature
+kPartTableOffset EQU 0x1be
+kMBRPartTable EQU kMBRBuffer + kPartTableOffset
+kExtPartTable EQU kExtBuffer + kPartTableOffset
-BOOT2_SIZE EQU 88 ; load this many blocks for boot2
-BOOT2_ADDR EQU 0x3000 ; where to load boot2
+kBoot2Sectors EQU 112 ; sectors to load for boot2
+kBoot2Address EQU 0x0000 ; boot2 load address
+kBoot2Segment EQU 0x2000 ; boot2 load segment
-DRIVE_NUM EQU 0x80 ; "C" drive
-SECTOR_BYTES EQU 512 ; sector size in bytes
+kSectorBytes EQU 512 ; sector size in bytes
+kBootSignature EQU 0xAA55 ; boot sector signature
-BUF_MBR EQU 0x1000 ; memory buffer for MBR
-BUF_EXT EQU 0x1200 ; memory buffer for extended partition
+kPartCount EQU 4 ; number of paritions per table
+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
-TABLE_MAIN EQU BUF_MBR + 0x1be ; location of main partition table
-TABLE_EXT EQU BUF_EXT + 0x1be ; location of ext partition table
-ENTRY_SIZE EQU 16 ; size of each fdisk partition entry
-TYPE_BOOT EQU 0xab ; partition type we are looking for
-TYPE_EXT EQU 0x05 ; extended partition type
-TYPE_EXT_1 EQU 0x0f ; Windows extended partition
-TYPE_EXT_2 EQU 0x85 ; Linux extended partition
-EXT_LEVELS_MAX EQU 128 ; max extended partition levels
+%ifdef FLOPPY
+kDriveNumber EQU 0x00
+%else
+kDriveNumber EQU 0x80
+%endif
+
+;
+; In memory variables.
+;
+ebios_lba dd 0 ; starting LBA of the intial extended partition.
+read_func dw 0 ; pointer to the LBA or CHS read function
-; Disk parameters gathered through INT13/F8 call.
;
-max_sectors db 0 ; number of sectors per track
-max_heads db 0 ; number of heads
+; Format of fdisk partition entry.
+;
+; The symbol 'part_size' is automatically defined as an `EQU'
+; 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
+.endhead resb 1 ; ending head, sector, cylinder
+.endsect: resb 1 ;
+.endcyl: resb 1 ;
+.lba: resd 1 ; starting lba
+.sectors resd 1 ; size in sectors
+ endstruc
-; Parameters to our load function.
;
-chs_cx dw 0 ; cx register for INT13/F2 call
-chs_dx dw 0 ; dx register for INT13/F2 call
+; Macros.
+;
+%macro DebugCharMacro 1
+ mov al, %1
+ call print_char
+%endmacro
+%if DEBUG
+%define DebugChar(x) DebugCharMacro x
+%else
+%define DebugChar(x)
+%endif
;--------------------------------------------------------------------------
; Start of text segment.
SEGMENT .text
- ORG 0xE000 ; must match BOOTRELOC
+ ORG 0xE000 ; must match kBoot0RelocAddr
;--------------------------------------------------------------------------
-; Loaded at 0:7c00h.
+; Boot code is loaded at 0:7C00h.
;
start
- ; Set up the stack to grow down from BOOTSEG:BOOTSP.
+ ;
+ ; Set up the stack to grow down from kBoot0Segment:kBoot0Stack.
; Interrupts should be off while the stack is being manipulated.
;
- cli ; interrupts off
- mov ax, BOOTSEG ;
- mov ss, ax ; ss <- BOOTSEG
- mov sp, BOOTSP ; sp <- BOOTSP
- sti ; reenable interrupts
+ cli ; interrupts off
+ xor ax, ax ; zero ax
+ mov ss, ax ; ss <- 0
+ mov sp, kBoot0Stack ; sp <- top of stack
+ sti ; reenable interrupts
+
+ mov es, ax ; es <- 0
+ mov ds, ax ; ds <- 0
- ; Relocate the booter code from DS:SI to ES:DI,
- ; or from 0:7C00h to BOOTSEG:BOOTRELOC.
;
- mov es, ax ; es <- BOOTSEG
- xor ax, ax
- mov ds, ax ; ds <- 0
- mov si, BOOTLOAD ; si <- BOOTLOAD (source)
- mov di, BOOTRELOC ; di <- BOOTRELOC (destination)
+ ; Relocate boot0 code.
;
- cld ; auto-increment SI and/or DI registers
- mov cx, 256 ; copy 256 words (512 bytes)
- repnz movsw ; repeat string move (word) operation
+ 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 BOOTSEG:start_reloc
+ jmp 0:start_reloc
;--------------------------------------------------------------------------
; Start execution from the relocated location.
;
-start_reloc
- mov ax, BOOTSEG
- mov ds, ax ; ds <- BOOTSEG
+start_reloc:
+
+ DebugChar('>')
- mov al, '=' ; indicate execution start
- call putchar
+ mov dl, kDriveNumber ; starting BIOS drive number
+
+.loop:
+
+%if DEBUG
+ mov al, dl
+ call print_hex
+%endif
- ; Get disk parameters (CHS) using INT13/F8 call.
;
- mov dl, DRIVE_NUM ; boot drive is drive C
- mov ah, 8 ; Read Disk Driver Parameter function
- int 0x13
- and cl, 0x3f ; sectors/track
- mov [max_sectors], cl
- mov [max_heads], dh
- jc error
-
- mov al, '>' ; indicate INT13/F8 success
- call putchar
-
- ; Since this code may not always reside in the MBR, we will always
- ; start by loading the MBR to BUF_MBR.
- ;
- mov WORD [chs_cx], 0x0001 ; cyl = 0, sect = 1
- mov BYTE [chs_dx + 1], 0 ; head = 0
- xor cx, cx ; skip 0 sectors
- mov ax, 1 ; read 1 sector
- mov bx, BUF_MBR ; load buffer
+ ; Clear various flags in memory.
+ ;
+ xor eax, eax
+ mov [ebios_lba], eax ; clear EBIOS LBA offset
+ mov WORD [read_func], read_chs ; assume CHS support
+
+ ;
+ ; 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
+ mov WORD [si], 0x0000 ; CHS DX: head = 0
+ mov WORD [si + 2], 0x0001 ; CHS CX: cylinder = 0, sector = 1
+
call load
- jc error
+ jc .next_drive ; MBR load error
- mov di, TABLE_MAIN ; argument for find_booter
- cmp WORD [di + 64], BOOTSIG ; correct signature found?
- jne error ; Oops! no signature!
- mov bl, TYPE_BOOT ; look for this partition type
- mov bh, 0 ; initial nesting level is 0
- call find_booter
+ ;
+ ; Check if EBIOS is supported for this hard drive.
+ ;
+ mov ah, 0x41 ; Function 0x41
+ mov bx, 0x55AA ; check signature
+; mov dl, kDriveNumber ; Drive number
+ int 0x13
-error
- mov si, load_error
- call message
-hang_1
- jmp hang_1
+ ;
+ ; 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
+ mov WORD [read_func], read_lba ; use read_lba for reads
+ DebugChar('E') ; EBIOS supported
+.ebios_check_done:
+
+ ;
+ ; Look for the booter partition in the MBR partition table,
+ ; which is at offset kMBRPartTable.
+ ;
+ mov di, kMBRPartTable ; pointer to partition table
+ mov ah, 0 ; initial nesting level is 0
+ 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
+
+ mov si, boot_error_str
+ call print_string
+
+hang:
+ jmp SHORT hang
;--------------------------------------------------------------------------
-; Locate the booter partition and load the booter.
+; Find the boot partition and load the booter from the partition.
;
; Arguments:
-; di - pointer to fdisk partition table.
-; bl - partition type to look for.
+; AH = recursion nesting level
+; DL = drive number (0x80 + unit number)
+; DI = pointer to fdisk partition table.
;
-; The following registers are modified:
-; ax, bh
+; Clobber list:
+; AX, BX, EBP
;
-find_booter
- push cx
+find_boot:
+ push cx ; preserve CX and SI
push si
- mov si, di ; si <- pointer to partition table
- mov cx, 4 ; 4 partition entries per table
-
-find_booter_pri
;
- ; Hunt for a fdisk partition type that matches the value in bl.
+ ; Check for boot block signature 0xAA55 following the 4 partition
+ ; entries.
;
-%IF DEBUG
- mov al, bh ; log partition type seen
- call putspace
- mov al, [si + 4]
- call display_byte
-%ENDIF
-
- cmp BYTE [si + 4], bl ; Is this the booter partition?
- je load_booter ; yes, load the booter
+ cmp WORD [di + part_size * kPartCount], kBootSignature
+ jne .exit ; boot signature not found
- add si, ENTRY_SIZE ; si <- next partition entry
- loop find_booter_pri ; loop while cx is not zero
+ mov si, di ; make SI a pointer to partition table
+ mov cx, kPartCount ; number of partition entries per table
- ; No primary (or perhaps logical) booter partition found in the
- ; current partition table. Restart and look for extended partitions.
+.loop:
;
- mov si, di ; si <- pointer to partition table
- mov cx, 4 ; 4 partition entries per table
+ ; First scan through the partition table looking for the boot
+ ; 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, ah ; indent based on nesting level
+ call print_spaces
+ mov al, [si + part.type] ; print partition type
+ call print_hex
+%endif
+
+ cmp BYTE [si + part.type], kPartTypeBoot
+ jne .continue
-find_booter_ext
;
- ; Look for extended partition entries in the partition table.
+ ; Found boot partition, read boot2 image to memory.
;
-%IF DEBUG
- mov al, bh ; log partition type seen
- call putspace
- mov al, 'E'
- call putchar
- mov al, [si + 4]
- call display_byte
-%ENDIF
+ mov al, kBoot2Sectors
+ mov bx, kBoot2Segment
+ mov es, bx
+ mov bx, kBoot2Address
+ call load ; will not return on success
+ jc .continue ; load error, keep looking?
- cmp BYTE [si + 4], TYPE_EXT ; Is this an extended partition?
- je find_booter_ext_2 ; yes, load its partition table
+ ;
+ ; Jump to boot2. The drive number is already in register DL.
+ ;
+ ; The first sector loaded from the disk is reserved for the boot
+ ; block (boot0), adjust the jump location by adding a sector offset.
+ ;
+ jmp kBoot2Segment:kBoot2Address + kSectorBytes
- cmp BYTE [si + 4], TYPE_EXT_1 ; Is this an extended partition?
- je find_booter_ext_2 ; yes, load its partition table
-
- cmp BYTE [si + 4], TYPE_EXT_2 ; Is this an extended partition?
- je find_booter_ext_2 ; yes, load its partition table
+.continue:
+ add si, part_size ; advance SI to next partition entry
+ loop .loop ; loop through all partition entries
-find_booter_ext_1
+%if EXT_PART_SUPPORT
;
- ; si is not pointing to an extended partition entry,
- ; try the next entry in the partition table.
+ ; No primary (or logical) boot partition found in the current
+ ; partition table. Restart and look for extended partitions.
;
- add si, ENTRY_SIZE ; si <- next partition entry
- loop find_booter_ext ; loop while cx is not zero
+ mov si, di ; make SI a pointer to partition table
+ mov cx, kPartCount ; number of partition entries per table
- jmp find_booter_end ; give up
+.ext_loop:
-find_booter_ext_2
- cmp bh, EXT_LEVELS_MAX
- ja find_booter_end ; in too deep!
+ mov al, [si + part.type] ; AL <- partition type
- inc bh ; increment nesting level counter
+ cmp al, kPartTypeExtDOS ; Extended DOS
+ je .ext_load
- ; Prepare the arguments for the load function call to
- ; load the extended partition table into memory.
- ; Note that si points to the extended partition entry.
- ;
- mov ax, [si] ; DH/DL
- mov [chs_dx], ax
- mov ax, [si + 2] ; CH/CL
- mov [chs_cx], ax
- pusha
- xor cx, cx ; skip 0 sectors
- mov ax, 1 ; read 1 sector
- mov bx, BUF_EXT ; load to BUF_EXT
- call load
- popa
+ cmp al, kPartTypeExtWin ; Extended Windows(95)
+ je .ext_load
- jc find_booter_ext_3 ; bail out if load failed
+ cmp al, kPartTypeExtLinux ; Extended Linux
+ je .ext_load
- mov di, TABLE_EXT ; di <- pointer to new partition table
- cmp WORD [di + 64], BOOTSIG
- jne find_booter_ext_3 ; OhOh! no signature!
+.ext_continue:
+ ;
+ ; 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
- call find_booter ; recursion...
+.ext_load:
+ ;
+ ; 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
-find_booter_ext_3
- dec bh ; decrement nesting level counter
+ ;
+ ; 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.
+ ;
+ or ah, ah
+ jnz .ext_find_boot
+ mov ebp, [si + part.lba]
+ mov [ebios_lba], ebp
+
+.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.
+ ;
+ inc ah ; increment recursion level
+ mov di, kExtPartTable ; partition table pointer
+ call find_boot ; recursion...
+ ;dec ah
- ; If we got here, then we know there isn't a booter
- ; partition linked from this partition entry.
+ ;
+ ; 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.
+ ;
- test bh, bh ; if we are at level 0, then
- jz find_booter_ext_1 ; look for next extended partition entry
+%endif ; EXT_PART_SUPPORT
-find_booter_end
+.exit:
+ ;
+ ; Boot partition not found. Giving up.
+ ;
pop si
pop cx
ret
;--------------------------------------------------------------------------
-; Yeah! Found the booter partition. The first sector in this partition
-; is reserved for the boot sector code (us). So load the booter
-; starting from the second sector in the partition, then jump to the
-; start of the booter.
-;
-load_booter
- mov ax, [si] ; DH/DL
- mov [chs_dx], ax
- mov ax, [si + 2] ; CH/CL
- mov [chs_cx], ax
-
- mov cx, 1 ; skip the initial boot sector
- mov ax, BOOT2_SIZE ; read BOOT2_SIZE sectors
- mov bx, BOOT2_ADDR ; where to place boot2 code
- call load ; load it...
-
- xor edx, edx ; argument for boot2 (hard drive boot)
- jmp BOOTSEG:BOOT2_ADDR ; there is no going back now!
-
-;--------------------------------------------------------------------------
-; Load sectors from disk using INT13/F2 call. The sectors are loaded
-; one sector at a time to avoid any BIOS bugs, and eliminate
-; complexities with crossing track boundaries, and other gotchas.
+; load - Load one or more sectors from a partition.
;
; Arguments:
-; cx - number of sectors to skip
-; ax - number of sectors to read
-; bx - pointer to the memory buffer (must not cross a segment boundary)
-; [chs_cx][chs_dx] - CHS starting position
+; 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
-; CF = 1 error
-;
-; The caller must save any registers it needs.
-;
-load
- jcxz load_sectors
- call next_sector ; [chs_cx][chs_dx] <- next sector
- loop load
-
-load_sectors
- mov cx, ax ; cx <- number of sectors to read
-
-load_loop
- call read_sector ; load a single sector
- jc load_exit ; abort if carry flag is set
- add bx, SECTOR_BYTES ; increment buffer pointer
- call next_sector ; [chs_cx][chs_dx] <- next sector
- loop load_loop
- clc ; successful exit
-load_exit
+; CF = 0 success
+; 1 error
+;
+load:
+ push cx
+ mov cx, 5 ; number of times to retry
+
+.loop:
+ call [read_func] ; call either read_chs or read_lba
+ jnc .exit ; load success
+ loop .loop ; retry on error
+
+.exit:
+ pop cx
ret
;--------------------------------------------------------------------------
-; Read a single sector from the hard disk.
+; read_chs - Read sectors from a partition using CHS addressing.
;
; Arguments:
-; [chs_cx][chs_dx] - CHS starting position
-; bx - pointer to the sector memory buffer
-; (must not cross a segment boundary)
+; 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
-; CF = 1 error
-;
-; Caller's cx register is preserved.
+; CF = 0 success
+; 1 error
;
-read_sector
- push cx
- mov cx, 5 ; try 5 times to read the sector
-
-read_sector_1
- mov bp, cx ; save cx
+read_chs:
+ pusha ; save all registers
- mov cx, [chs_cx]
- mov dx, [chs_dx]
- mov dl, DRIVE_NUM ; drive number
- mov ax, 0x0201 ; Func 2, read 1 sector
- int 0x13 ; read sector
- jnc read_sector_ok ; CF = 0 indicates success
-
- mov al, '*' ; sector read error indicator
- call putchar
+ ;
+ ; Read the CHS start values from the partition entry.
+ ;
+ mov dh, [ si + part.head ] ; drive head
+ mov cx, [ si + part.sect ] ; drive sector + cylinder
- xor ax, ax ; Reset the drive and retry the read
- int 0x13
+ ;
+ ; 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 dl, kDriveNumber
+ mov ah, 0x02 ; Func 2
+ int 0x13 ; INT 13
+ jnc .exit
- mov cx, bp
- loop read_sector_1 ; retry while cx is not zero
+ DebugChar('e') ; indicate INT13/F2 error
- stc ; set carry flag to indicate error
- pop cx
- ret
+ ;
+ ; 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
-read_sector_ok
- mov al, '.' ; successful sector read indicator
- call putchar
- clc ; success, clear carry flag
- pop cx
+.exit:
+ popa
ret
;--------------------------------------------------------------------------
-; Given the current CHS position stored in [chs_cx][chs_dx], update
-; it so that the value in [chs_cx][chs_dx] points to the following
-; sector.
+; read_lba - Read sectors from a partition using LBA addressing.
;
; Arguments:
-; [chs_cx][chs_dx] - CHS position
-;
-; [max_sectors] and [max_heads] must be valid.
+; 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)
+; SI = pointer to the partition entry.
;
-; Caller's ax and bx registers are preserved.
+; Returns:
+; CF = 0 success
+; 1 error
;
-next_sector
- push ax
- push bx
+read_lba:
+ pusha ; save all registers
+ mov bp, sp ; save current SP
- ; Extract the CHS values from the packed register values in memory.
;
- mov al, [chs_cx]
- and al, 0x3f ; al <- sector number (1-63)
+ ; Create the Disk Address Packet structure for the
+ ; INT13/F42 (Extended Read Sectors) on the stack.
+ ;
- mov bx, [chs_cx]
- rol bl, 2
- ror bx, 8
- and bx, 0x03ff ; bx <- cylinder number
+ ; 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 ah, [chs_dx + 1] ; ah <- head number
+ mov ecx, [ebios_lba] ; offset 8, lower 32-bit LBA
+ add ecx, [si + part.lba]
+ push ecx
- inc al ; Increment CHS by one sector.
- cmp al, [max_sectors]
- jbe next_sector_done
+ push es ; offset 6, memory segment
- inc ah
- cmp ah, [max_heads]
- jbe next_sector_new_head
+ push bx ; offset 4, memory offset
- inc bx
+ xor ah, ah ; offset 3, must be 0
+ push ax ; offset 2, number of sectors
-next_sector_new_cyl
- xor ah, ah ; head number starts at 0
+ push WORD 16 ; offset 0-1, packet size
-next_sector_new_head
- mov al, 1 ; sector number starts at 1
+ ;
+ ; INT13 Func 42 - Extended Read Sectors
+ ;
+ ; Arguments:
+ ; AH = 0x42
+ ; DL = drive number (80h + drive unit)
+ ; DS:SI = pointer to Disk Address Packet
+ ;
+ ; Returns:
+ ; AH = return status (sucess is 0)
+ ; carry = 0 success
+ ; 1 error
+ ;
+ ; Packet offset 2 indicates the number of sectors read
+ ; successfully.
+ ;
+; mov dl, kDriveNumber
+ mov si, sp
+ mov ah, 0x42
+ int 0x13
+
+ jnc .exit
-next_sector_done
- ; Reassemble the CHS values back into the packed representation
- ; in memory.
+ DebugChar('E') ; indicate INT13/F42 error
+
+ ;
+ ; Issue a disk reset on error.
+ ; Should this be changed to Func 0xD to skip the diskette controller
+ ; reset?
;
- mov [chs_cx + 1], bl ; lower 8-bits of the 10-bit cylinder
- ror bh, 2
- or bh, al
- mov [chs_cx], bh ; cylinder & sector number
- mov [chs_dx + 1], ah ; head number
+ xor ax, ax ; Func 0
+ int 0x13 ; INT 13
+ stc ; set carry to indicate error
- pop bx
- pop ax
+.exit:
+ mov sp, bp ; restore SP
+ popa
ret
;--------------------------------------------------------------------------
; Write a string to the console.
;
; Arguments:
-; ds:si pointer to a NULL terminated string.
-;
-; The following registers are modified:
-; ax, bx, si
-;
-message
- mov bx, 1 ; bh=0, bl=1 (blue)
- cld ; increment SI after each lodsb call
-message_loop
- lodsb ; load a byte from DS:SI into al
- cmp al, 0 ; Is it a NULL?
- je message_done ; yes, all done
- mov ah, 0xE ; bios INT10 Func 0xE
- int 0x10 ; bios display a byte in tty mode
- jmp short message_loop
-message_done
+; DS:SI pointer to a NULL terminated string.
+;
+; Clobber list:
+; AX, BX, SI
+;
+print_string
+ mov bx, 1 ; BH=0, BL=1 (blue)
+ cld ; increment SI after each lodsb call
+.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
ret
+%if DEBUG
+
;--------------------------------------------------------------------------
; Write a ASCII character to the console.
;
; Arguments:
-; al contains the ASCII character printed.
-;
-putchar
- push bx
- mov bx, 1 ; bh=0, bl=1 (blue)
- mov ah, 0x0e ; bios int 10, function 0xe
- int 0x10 ; bios display a byte in tty mode
- pop bx
- ret
-
-%IF DEBUG
-;==========================================================================
-; DEBUG FUNCTION START
+; AL = ASCII character.
;
-; If DEBUG is set to 1, this booter will become too large for the MBR,
-; but it will still be less than 510 bytes, which is fine for a partition's
-; boot sector.
-;==========================================================================
+print_char
+ pusha
+ mov bx, 1 ; BH=0, BL=1 (blue)
+ mov ah, 0x0e ; bios INT 10, Function 0xE
+ int 0x10 ; display byte in tty mode
+ popa
+ ret
;--------------------------------------------------------------------------
; Write a variable number of spaces to the console.
;
; Arguments:
-; al number to spaces to display
+; AL = number to spaces.
;
-putspace
- push cx
+print_spaces:
+ pusha
xor cx, cx
- mov cl, al ; use cx as the loop counter
- mov al, ' ' ; character to print
-putspace_loop
- jcxz putspace_done
- call putchar
- loop putspace_loop
-putspace_done
- pop cx
+ mov cl, al ; use CX as the loop counter
+ mov al, ' ' ; character to print
+.loop:
+ jcxz .exit
+ call print_char
+ loop .loop
+.exit:
+ popa
ret
;--------------------------------------------------------------------------
-; Write the hex byte value to the console.
+; Write the byte value to the console in hex.
;
; Arguments:
-; al contains the byte to be displayed. e.g. if al is 0x3f, then 3F
-; will be displayed on screen.
+; AL = Value to be displayed in hex.
;
-display_byte
+print_hex:
push ax
ror al, 4
- call display_nibble ; display upper nibble
+ call print_nibble ; display upper nibble
pop ax
- call display_nibble ; display lower nibble
- ;
- mov ax, 10 ; display carriage return
- call putchar
- mov ax, 13
- call putchar
+ call print_nibble ; display lower nibble
+
+ mov al, 10 ; carriage return
+ call print_char
+ mov al, 13
+ call print_char
ret
-display_nibble
+print_nibble:
and al, 0x0f
add al, '0'
cmp al, '9'
- jna display_nibble_1
+ jna .print_ascii
add al, 'A' - '9' - 1
-display_nibble_1
- call putchar
+.print_ascii:
+ call print_char
ret
-;==========================================================================
-; DEBUG FUNCTION END
-;==========================================================================
-%ENDIF
+%endif ; DEBUG
;--------------------------------------------------------------------------
; NULL terminated strings.
;
-load_error db 10, 13, 'Load Error', 0
+boot_error_str db 10, 13, 'Boot Error', 0
;--------------------------------------------------------------------------
; Pad the rest of the 512 byte sized booter with zeroes. The last
; that the 'times' argument is negative.
pad_boot
- times 446-($-$$) db 0
+ times 446-($-$$) db 0
+
+%ifdef FLOPPY
+;--------------------------------------------------------------------------
+; Put fake partition entries for the bootable floppy image
+;
+part1bootid db 0x80 ; first partition active
+part1head db 0x00 ; head #
+part1sect db 0x02 ; sector # (low 6 bits)
+part1cyl db 0x00 ; cylinder # (+ high 2 bits of above)
+part1systid db 0xab ; Apple boot partition
+times 3 db 0x00 ; ignore head/cyl/sect #'s
+part1relsect dd 0x00000001 ; start at sector 1
+part1numsect dd 0x00000080 ; 64K for booter
+part2bootid db 0x00 ; not active
+times 3 db 0x00 ; ignore head/cyl/sect #'s
+part2systid db 0xa8 ; Apple UFS partition
+times 3 db 0x00 ; ignore head/cyl/sect #'s
+part2relsect dd 0x00000082 ; start after booter
+; part2numsect dd 0x00000abe ; 1.44MB - 65K
+part2numsect dd 0x000015fe ; 2.88MB - 65K
+%endif
pad_table_and_sig
times 510-($-$$) db 0
- dw BOOTSIG
+ dw kBootSignature
END
; This code is written for the NASM assembler.
; nasm boot0.s -o boot0
+
;--------------------------------------------------------------------------
; Constants.
BOOTRELOC EQU 0xE000 ; booter is relocated here
BOOTSIG EQU 0xAA55 ; booter signature
-BOOT2_SIZE EQU 88 ; load this many blocks for boot2
-BOOT2_ADDR EQU 0x3000 ; where to load boot2
+BOOT2_SIZE EQU 112 ; load this many blocks for boot2
+BOOT2_ADDR EQU 0x0200 ; where to load boot2
+BOOT2_SEG EQU 0x2000
%IF BOOTDEV = FLOPPY
-DRIVE_NUM EQU FLOPPY ; floppy drive
+DRIVE_NUM EQU FLOPPY ; floppy drive
%ELSE
-DRIVE_NUM EQU HDISK ; "C" drive
+DRIVE_NUM EQU HDISK ; "C" drive
%ENDIF
SECTOR_BYTES EQU 512 ; sector size in bytes
; or from 0:7C00h to BOOTSEG:BOOTRELOC.
;
mov es, ax ; es <- BOOTSEG
- xor ax, ax
- mov ds, ax ; ds <- 0
+ mov ds, ax ; ds <- BOOTSEG
+
mov si, BOOTLOAD ; si <- BOOTLOAD (source)
mov di, BOOTRELOC ; di <- BOOTRELOC (destination)
;
; Start execution from the relocated location.
;
start_reloc
- mov ax, BOOTSEG
- mov ds, ax ; ds <- BOOTSEG
-
mov al, '=' ; indicate execution start
call putchar
mov al, '>' ; indicate INT13/F8 success
call putchar
- mov ax, BOOTSEG ; es <- BOOTSEG
- mov es, ax
-
; Since this code may not always reside in the MBR, we will always
; start by loading the MBR to BUF_MBR.
;
cmp BYTE [si + 4], TYPE_EXT_1 ; Is this an extended partition?
je find_booter_ext_2 ; yes, load its partition table
-
+
cmp BYTE [si + 4], TYPE_EXT_2 ; Is this an extended partition?
je find_booter_ext_2 ; yes, load its partition table
mov cx, 1 ; skip the initial boot sector
mov ax, BOOT2_SIZE ; read BOOT2_SIZE sectors
+ mov bx, BOOT2_SEG
+ mov es, bx
mov bx, BOOT2_ADDR ; where to place boot2 code
call load ; load it...
- xor edx, edx ; argument for boot2 (hard drive boot)
-%IF BOOTDEV = FLOPPY
- inc edx ; floppy is dev 1
-%ENDIF
- jmp BOOTSEG:BOOT2_ADDR ; there is no going back now!
+ xor edx, edx
+ mov dl, DRIVE_NUM ; argument for boot2
+
+ jmp BOOT2_SEG:BOOT2_ADDR ; there is no going back now!
;--------------------------------------------------------------------------
; Load sectors from disk using INT13/F2 call. The sectors are loaded
;
; Arguments:
; [chs_cx][chs_dx] - CHS starting position
-; bx - pointer to the sector memory buffer
-; (must not cross a segment boundary)
+; es:bx - pointer to the sector memory buffer
+; (must not cross a segment boundary)
;
; Returns:
; CF = 0 success
; that the 'times' argument is negative.
pad_boot
- times 446-($-$$) db 0
+ times 446-($-$$) db 0
%IF BOOTDEV = FLOPPY
;--------------------------------------------------------------------------
; Put fake partition entries for the bootable floppy image
;
-part1bootid db 0x80 ; first partition active
-part1head db 0x00 ; head #
-part1sect db 0x02 ; sector # (low 6 bits)
-part1cyl db 0x00 ; cylinder # (+ high 2 bits of above)
-part1systid db 0xab ; Apple boot partition
-times 3 db 0x00 ; ignore head/cyl/sect #'s
-part1relsect dd 0x00000001 ; start at sector 1
-part1numsect dd 0x00000058 ; 44K for booter
-part2bootid db 0x00 ; not active
-times 3 db 0x00 ; ignore head/cyl/sect #'s
-part2systid db 0xa8 ; Apple UFS partition
-times 3 db 0x00 ; ignore head/cyl/sect #'s
-part2relsect dd 0x0000005a ; start after booter
-; part2numsect dd 0x00000ae6 ; 1.44MB - 45K
-part2numsect dd 0x00001626 ; 2.88MB - 45K
+part1bootid db 0x80 ; first partition active
+part1head db 0x00 ; head #
+part1sect db 0x02 ; sector # (low 6 bits)
+part1cyl db 0x00 ; cylinder # (+ high 2 bits of above)
+part1systid db 0xab ; Apple boot partition
+times 3 db 0x00 ; ignore head/cyl/sect #'s
+part1relsect dd 0x00000001 ; start at sector 1
+part1numsect dd 0x00000080 ; 64K for booter
+part2bootid db 0x00 ; not active
+times 3 db 0x00 ; ignore head/cyl/sect #'s
+part2systid db 0xa8 ; Apple UFS partition
+times 3 db 0x00 ; ignore head/cyl/sect #'s
+part2relsect dd 0x00000082 ; start after booter
+; part2numsect dd 0x00000abe ; 1.44MB - 65K
+part2numsect dd 0x000015fe ; 2.88MB - 65K
%ENDIF
pad_table_and_sig
include ../MakePaths.dir
OPTIM = -Os
-CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Wno-precomp \
- -munaligned-text -DSAIO_INTERNAL_USER -static -traditional-cpp
+CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
+ -fno-builtin -DSAIO_INTERNAL_USER -static
DEFINES=
CONFIG = hd
SYMDIR = $(SYMROOT)
# The ordering is important;
# boot2.o must be first.
-OBJS = boot2.o boot.o graphics.o drivers.o prompt.o
+OBJS = boot2.o boot.o graphics.o drivers.o prompt.o options.o
# button.o browser.o scrollbar.o == NOTYET
UTILDIR = ../util
SFILES = boot2.s
-CFILES = boot.c graphics.c drivers.c prompt.c
+CFILES = boot.c graphics.c drivers.c prompt.c options.c
HFILES = boot.h
OTHERFILES = Makefile
ALLSRC = $(FOREIGNSRC) $(FOREIGNBIN) $(SFILES) $(CFILES) \
$(HFILES) $(OTHERFILES)
DIRS_NEEDED = $(OBJROOT) $(SYMROOT)
-BOOT2ADDR = 3000
-MAXBOOTSIZE = 45056
+BOOT2ADDR = 20200
+MAXBOOTSIZE = 65024
all: $(DIRS_NEEDED) boot
--- /dev/null
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License"). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __BOOT2_APPLECLUT8_H
+#define __BOOT2_APPLECLUT8_H
+
+static const unsigned char appleClut8[ 256 * 3 ] =
+{
+ 0xff,0xff,0xff, 0xfe,0xfe,0xfe, 0xfd,0xfd,0xfd, 0xb8,0x27,0x2b,
+ 0xfc,0xfc,0xfc, 0xff,0xff,0x00, 0xfa,0xfa,0xfa, 0xf9,0xf9,0xf9,
+ 0xf8,0xf8,0xf8, 0xf7,0xf7,0xf7, 0xf6,0xf6,0xf6, 0xf5,0xf5,0xf5,
+ 0xf4,0xf4,0xf4, 0xf2,0xf2,0xf2, 0xf1,0xf1,0xf1, 0x00,0x00,0x00,
+ 0xef,0xef,0xef, 0xee,0xee,0xee, 0xed,0xed,0xed, 0xeb,0xeb,0xeb,
+ 0xe8,0xe8,0xe8, 0xe7,0xe7,0xe7, 0xc9,0x38,0x3e, 0xe5,0xe5,0xe5,
+ 0xff,0x00,0xff, 0xfb,0xfb,0xfb, 0xde,0x6c,0x72, 0xe0,0xe0,0xe0,
+ 0xe8,0x86,0x90, 0xde,0xde,0xde, 0xdd,0xdd,0xdd, 0xd3,0x7e,0x8d,
+ 0xd9,0xd9,0xd9, 0xf3,0x96,0xa6, 0xb1,0x1c,0x39, 0xff,0x00,0x00,
+ 0xbe,0x5e,0x72, 0xd3,0xd3,0xd3, 0xc6,0x2e,0x67, 0xd1,0xd1,0xd1,
+ 0xa3,0x06,0x45, 0xce,0xce,0xce, 0xcc,0xcc,0xff, 0xcc,0xcc,0xcc,
+ 0xc6,0x8f,0xa7, 0xe1,0xd3,0xd9, 0xce,0x9e,0xb4, 0xca,0xca,0xca,
+ 0xbf,0x3f,0x7d, 0xc9,0xc9,0xc9, 0xf4,0x89,0xbe, 0xc6,0xc6,0xc6,
+ 0xd6,0x51,0x97, 0xc9,0x2c,0x84, 0x96,0x1a,0x6a, 0xc2,0xc2,0xc2,
+ 0xf3,0x6f,0xc6, 0xe5,0x4c,0xbb, 0xb7,0x5a,0x9c, 0xbf,0xbf,0xbf,
+ 0xbe,0xbe,0xbe, 0xbd,0xbd,0xbd, 0xb8,0x21,0xa2, 0xd3,0x44,0xc0,
+ 0xc2,0x66,0xb7, 0xf4,0x66,0xe6, 0xfc,0x73,0xfd, 0xb9,0xb9,0xb9,
+ 0xea,0xdf,0xea, 0xd4,0x71,0xd5, 0xf9,0x8b,0xff, 0xf5,0xad,0xff,
+ 0xbc,0x92,0xc2, 0xc7,0x4f,0xd9, 0xa0,0x44,0xaf, 0xc8,0x8c,0xd5,
+ 0xd7,0x74,0xf7, 0xb4,0xb4,0xb4, 0xda,0x95,0xf9, 0xed,0xcb,0xff,
+ 0xb2,0xb2,0xb2, 0xa1,0x61,0xd7, 0xb2,0x85,0xe2, 0x59,0x26,0x9c,
+ 0x7c,0x51,0xcc, 0xb0,0xb0,0xb0, 0xb4,0x8e,0xfc, 0xd5,0xc0,0xff,
+ 0x5d,0x32,0xcc, 0x7b,0x5c,0xe5, 0xc0,0xb0,0xfd, 0x60,0x53,0xad,
+ 0x12,0x0c,0x7e, 0x2e,0x29,0x99, 0x79,0x78,0xe9, 0x5b,0x5c,0xd0,
+ 0x69,0x6a,0xcc, 0x93,0x94,0xf8, 0x92,0x92,0xc3, 0x41,0x44,0xba,
+ 0xa8,0xab,0xff, 0xa3,0xa3,0xa3, 0xdb,0xdd,0xea, 0x31,0x49,0xaa,
+ 0x70,0x8f,0xf9, 0x48,0x66,0xc1, 0x5c,0x7e,0xe9, 0xe2,0xe5,0xeb,
+ 0xb0,0xcd,0xff, 0x6c,0x89,0xb7, 0x34,0x65,0xaf, 0x8c,0xb9,0xff,
+ 0x37,0x79,0xd4, 0x5a,0x99,0xea, 0x0e,0x4c,0x95, 0x79,0xb9,0xff,
+ 0x8a,0xa3,0xbc, 0x20,0x61,0x9d, 0x8f,0xae,0xca, 0x0a,0x60,0xa8,
+ 0x3f,0x94,0xd9, 0x63,0xb5,0xf9, 0xe2,0xe8,0xed, 0x28,0x6a,0x99,
+ 0x55,0xb2,0xe7, 0x32,0x89,0xa9, 0xcf,0xda,0xde, 0x29,0xa1,0xc7,
+ 0x86,0xa9,0xb4, 0x00,0x5f,0x79, 0x0c,0x77,0x8e, 0x12,0x8f,0xab,
+ 0x41,0xba,0xd5, 0x24,0x82,0x83, 0x2c,0xc4,0xc3, 0x1a,0xab,0xa6,
+ 0x4b,0xa8,0xa2, 0x0a,0x93,0x85, 0x0d,0xa5,0x96, 0x26,0xbc,0xac,
+ 0x04,0x81,0x72, 0x19,0xb3,0x86, 0x29,0xc1,0x94, 0x21,0x9c,0x71,
+ 0x02,0x8c,0x50, 0x35,0xd0,0x89, 0x46,0xa5,0x76, 0x02,0x7d,0x39,
+ 0x29,0xc9,0x71, 0x57,0xd6,0x8f, 0xa2,0xb5,0xaa, 0x01,0x88,0x2a,
+ 0x74,0xbe,0x8a, 0x19,0xb6,0x47, 0x2d,0xc6,0x51, 0x38,0xde,0x5d,
+ 0x4c,0xf4,0x6f, 0x91,0x9c,0x93, 0x00,0x8e,0x19, 0x10,0xaf,0x28,
+ 0xe3,0xe3,0xe3, 0x08,0xa1,0x1a, 0x59,0xc2,0x61, 0xf0,0xf0,0xf0,
+ 0x8f,0x9c,0x90, 0x23,0xce,0x2a, 0x12,0xba,0x17, 0x01,0x8a,0x02,
+ 0x03,0x9a,0x02, 0x40,0xe4,0x40, 0x08,0xb2,0x05, 0x13,0xcc,0x0f,
+ 0x36,0xd7,0x32, 0x28,0xe9,0x1f, 0x53,0xfb,0x4c, 0x6f,0xaf,0x6a,
+ 0x71,0xe0,0x67, 0x32,0xc0,0x12, 0x29,0xa5,0x08, 0x5c,0xdd,0x35,
+ 0x00,0xff,0xff, 0x63,0xc8,0x45, 0x86,0xfd,0x5b, 0x71,0xf6,0x39,
+ 0x55,0xcc,0x15, 0x00,0xff,0x00, 0x90,0xca,0x6e, 0x43,0xa7,0x01,
+ 0x8d,0xe4,0x37, 0xb3,0xf0,0x64, 0x85,0x8e,0x7a, 0xb0,0xfa,0x4d,
+ 0xd6,0xd6,0xd6, 0x88,0xd0,0x1a, 0x6a,0xa7,0x03, 0x98,0xbf,0x41,
+ 0xcd,0xf8,0x51, 0x94,0xa4,0x55, 0x91,0xb0,0x0a, 0xda,0xf1,0x3c,
+ 0xba,0xca,0x53, 0xb9,0xc3,0x28, 0xb1,0xba,0x12, 0xd2,0xd9,0x26,
+ 0xe8,0xec,0x2d, 0x98,0x96,0x02, 0xad,0xad,0x5c, 0xe2,0xd8,0x38,
+ 0xd9,0xc4,0x38, 0xa8,0x9a,0x50, 0x00,0x00,0xff, 0xbe,0xae,0x5e,
+ 0x9a,0x98,0x8e, 0xac,0x8d,0x0d, 0xc5,0xa0,0x2b, 0xdb,0xb5,0x48,
+ 0xdd,0x00,0x00, 0x9c,0x6d,0x03, 0xd4,0xa8,0x47, 0xb7,0x71,0x17,
+ 0xdc,0xa1,0x5a, 0xb9,0x9c,0x7c, 0xb4,0xab,0xa2, 0x9e,0x4b,0x01,
+ 0xc8,0x78,0x35, 0xd2,0x8d,0x51, 0xad,0x52,0x0f, 0x00,0xbb,0x00,
+ 0xb2,0x66,0x38, 0xb1,0xa6,0x9f, 0xb1,0x87,0x6f, 0xa4,0x34,0x03,
+ 0xee,0x9e,0x85, 0xc9,0x73,0x5a, 0xe6,0x94,0x7c, 0xa9,0x22,0x06,
+ 0xdb,0x87,0x74, 0xb0,0x2e,0x15, 0xb7,0x5a,0x50, 0xb2,0x42,0x3b,
+ 0xcd,0x73,0x6e, 0xd9,0x58,0x58, 0xac,0xac,0xac, 0xa0,0xa0,0xa0,
+ 0x9a,0x9a,0x9a, 0x92,0x92,0x92, 0x8e,0x8e,0x8e, 0xbb,0xbb,0xbb,
+ 0x81,0x81,0x81, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55,
+ 0x44,0x44,0x44, 0x22,0x22,0x22, 0x7b,0x7b,0x7b, 0x00,0x00,0x00
+};
+
+#endif /* !__BOOT2_APPLECLUT8_H */
* Completely reworked by Sam Streeper (sam_s@NeXT.com)
* Reworked again by Curtis Galloway (galloway@NeXT.com)
*/
-#include "libsa.h"
-#include "memory.h"
-#include "saio.h"
-#include "libsaio.h"
-#include "kernBootStruct.h"
+
#include "boot.h"
-#include "nbp.h"
/*
* The user asked for boot graphics.
*/
-static BOOL gWantBootGraphics = NO;
-
-/*
- * The device that the booter was loaded from.
- */
-int gBootDev;
+BOOL gBootGraphics = NO;
+int gBIOSDev;
+long gBootMode = kBootModeNormal;
-extern char * gFilename;
-extern BOOL sysConfigValid;
-extern char bootPrompt[];
-extern BOOL errors;
-extern BOOL gVerboseMode;
-extern BOOL gSilentBoot;
-
-/*
- * Prototypes.
- */
-static void getBootString();
+static BOOL gUnloadPXEOnExit = 0;
/*
* How long to wait (in seconds) to load the
* kernel after displaying the "boot:" prompt.
*/
-#define kBootTimeout 10
+#define kBootErrorTimeout 5
//==========================================================================
// Zero the BSS.
-static void
-zeroBSS()
+static void zeroBSS()
{
extern char _DATA__bss__begin, _DATA__bss__end;
extern char _DATA__common__begin, _DATA__common__end;
//==========================================================================
// execKernel - Load the kernel image (mach-o) and jump to its entry point.
-static int
-execKernel(int fd)
+static int execKernel(int fd)
{
register KERNBOOTSTRUCT * kbp = kernBootStruct;
static struct mach_header head;
kbp->kaddr = kbp->ksize = 0;
- ret = loadprog( kbp->kernDev,
- fd,
+ ret = loadprog( kbp->kernDev, fd,
&head,
&kernelEntry,
(char **) &kbp->kaddr,
if ( ret != 0 )
return ret;
- // Load boot drivers from the specifed root.
+ // Load boot drivers from the specifed root path.
LoadDrivers("/");
clearActivityIndicator();
- if (errors) {
+ if (gErrors) {
printf("Errors encountered while starting up the computer.\n");
- printf("Pausing %d seconds...\n", kBootTimeout);
- sleep(kBootTimeout);
+ printf("Pausing %d seconds...\n", kBootErrorTimeout);
+ sleep(kBootErrorTimeout);
}
- message("Starting Darwin/x86", 0);
+ printf("Starting Darwin/x86");
turnOffFloppy();
// Cleanup the PXE base code.
- if ( gBootDev == kBootDevNetwork )
+ if ( gUnloadPXEOnExit )
{
if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess )
{
- printf("nbpUnloadBaseCode error %d\n", (int) ret); sleep(2);
+ printf("nbpUnloadBaseCode error %d\n", (int) ret);
+ sleep(2);
}
}
- // Switch to graphics mode just before starting the kernel.
+ // Switch to desired video mode just before starting the kernel.
- if ( gWantBootGraphics )
- {
- setMode(GRAPHICS_MODE);
- }
+ setVideoMode( gBootGraphics ? GRAPHICS_MODE : TEXT_MODE );
// Jump to kernel's entry point. There's no going back now.
- startprog(kernelEntry);
+ startprog( kernelEntry );
// Not reached
}
//==========================================================================
-// Scan and record the system's PCI bus information.
+// Scan and record the system's hardware information.
static void scanHardware()
{
-extern int ReadPCIBusInfo(PCI_bus_info_t *);
-extern void PCI_Bus_Init(PCI_bus_info_t *);
+ extern int ReadPCIBusInfo(PCI_bus_info_t *);
+ extern void PCI_Bus_Init(PCI_bus_info_t *);
ReadPCIBusInfo( &kernBootStruct->pciInfo );
- PCI_Bus_Init( &kernBootStruct->pciInfo );
+
+ //
+ // Initialize PCI matching support in the booter.
+ // Not used, commented out to minimize code size.
+ //
+ // PCI_Bus_Init( &kernBootStruct->pciInfo );
}
//==========================================================================
-// The 'main' function for the booter. This function is called by the
-// assembly routine init(), which is in turn called by boot1 or by
-// NBP.
+// The 'main' function for the booter. Called by boot0 when booting
+// from a block device, or by the network booter.
//
// arguments:
-// bootdev - Value passed from boot1/NBP to specify the device
-// that the booter was loaded from. See boot.h for the list
-// of allowable values.
+// biosdev - Value passed from boot1/NBP to specify the device
+// that the booter was loaded from.
//
-// If bootdev is kBootDevNetwork, then this function will return if
+// If biosdev is kBIOSDevNetwork, then this function will return if
// booting was unsuccessful. This allows the PXE firmware to try the
-// next bootable device on its list. If bootdev is not kBootDevNetwork,
-// this function will not return control back to the caller.
+// next boot device on its list.
-void
-boot(int bootdev)
+void boot(int biosdev)
{
register KERNBOOTSTRUCT * kbp = kernBootStruct;
int fd;
+ int status;
zeroBSS();
enableA20();
- // Remember the device that the booter was loaded from.
+ // Set reminder to unload the PXE base code. Neglect to unload
+ // the base code will result in a hang or kernel panic.
+
+ if ( BIOS_DEV_TYPE(biosdev) == kBIOSDevTypeNetwork )
+ gUnloadPXEOnExit = 1;
+
+#if 0
+ gUnloadPXEOnExit = 1;
+ biosdev = 0x80;
+#endif
- gBootDev = bootdev;
+ // Record the device that the booter was loaded from.
+
+ gBIOSDev = biosdev & kBIOSDevMask;
// Initialize boot info structure.
- initKernBootStruct();
+ initKernBootStruct( gBIOSDev );
// Setup VGA text mode.
+ // Not sure if it is safe to call setVideoMode() before the
+ // config table has been loaded. Call video_mode() instead.
- setMode(TEXT_MODE);
+ video_mode( 2 ); // 80x25 mono text mode.
// Scan hardware configuration.
scanHardware();
- // Display boot prompt.
+ // Display banner and show hardware info.
- printf( bootPrompt, kbp->convmem, kbp->extmem, kBootTimeout );
+ setCursorPosition( 0, 0, 0 );
+ printf( bootBanner, kbp->convmem, kbp->extmem );
+ printVBEInfo();
// Parse args, load and start kernel.
// Initialize globals.
sysConfigValid = 0;
- errors = 0;
-
- // Make sure we are in VGA text mode.
-
- setMode(TEXT_MODE);
-
- // Set up kbp->kernDev to reflect the boot device.
-
- if ( bootdev == kBootDevHardDisk )
- {
- if (kbp->numIDEs > 0)
- {
- kbp->kernDev = DEV_HD;
- }
- else
- {
- kbp->kernDev = DEV_SD;
- }
- }
- else if ( bootdev == kBootDevFloppyDisk )
- {
- kbp->kernDev = DEV_FLOPPY;
- }
- else
- {
- kbp->kernDev = DEV_EN;
- }
- flushdev();
+ gErrors = 0;
- // Display boot prompt and get user supplied boot string.
-
- getBootString();
-
- if ( bootdev != kBootDevNetwork )
- {
- // To force loading config file off same device as kernel,
- // open kernel file to force device change if necessary.
-
- fd = open(kbp->bootFile, 0);
- if (fd >= 0) close(fd);
- }
-
- if ( sysConfigValid == 0 )
- {
- if (kbp->kernDev == DEV_EN)
- break; // return control back to PXE
- else
- continue; // keep looping
- }
+ getBootOptions();
+ status = processBootOptions();
+ if ( status == 1 ) break;
+ if ( status == -1 ) continue;
// Found and loaded a config file. Proceed with boot.
- gWantBootGraphics = getBoolForKey( kBootGraphicsKey );
- gSilentBoot = getBoolForKey( kQuietBootKey );
-
- message("Loading Darwin/x86", 0);
+ printf("Loading Darwin/x86\n");
- if ( (fd = openfile(kbp->bootFile, 0)) >= 0 )
+ if ( (fd = openfile( kbp->bootFile, 0 )) >= 0 )
{
execKernel(fd); // will not return on success
}
{
error("Can't find %s\n", kbp->bootFile);
- if ( bootdev == kBootDevFloppyDisk )
+ if ( BIOS_DEV_TYPE(gBIOSDev) == kBIOSDevTypeFloppy )
{
// floppy in drive, but failed to load kernel.
- bootdev = kBootDevHardDisk;
- message("Couldn't start up the computer using this "
- "floppy disk.", 0);
+ gBIOSDev = kBIOSDevTypeHardDrive;
+ initKernBootStruct( gBIOSDev );
+ printf("Attempt to load from hard drive.");
}
- else if ( bootdev == kBootDevNetwork )
+ else if ( BIOS_DEV_TYPE(gBIOSDev) == kBIOSDevTypeNetwork )
{
- break; // Return control back to PXE.
+ // Return control back to PXE. Don't unload PXE base code.
+ gUnloadPXEOnExit = 0;
+ break;
}
}
} /* while(1) */
-}
-
-//==========================================================================
-// Skip spaces/tabs characters.
-
-static inline void
-skipblanks(char ** cp)
-{
- while ( **(cp) == ' ' || **(cp) == '\t' )
- ++(*cp);
-}
-
-//==========================================================================
-// Load the help file and display the file contents on the screen.
-
-static void showHelp()
-{
-#define BOOT_DIR_DISK "/usr/standalone/i386/"
-#define BOOT_DIR_NET ""
-#define makeFilePath(x) \
- (gBootDev == kBootDevNetwork) ? BOOT_DIR_NET x : BOOT_DIR_DISK x
-
- int fd;
- char * help = makeFilePath("BootHelp.txt");
-
- if ( (fd = open(help, 0)) >= 0 )
- {
- char * buffer = malloc( file_size(fd) );
- read(fd, buffer, file_size(fd) - 1);
- close(fd);
- printf("%s", buffer);
- free(buffer);
- }
-}
-
-//==========================================================================
-// Returns 1 if the string pointed by 'cp' contains an user-specified
-// kernel image file name. Used by getBootString() function.
-
-static int
-containsKernelName(const char * cp)
-{
- register char c;
-
- skipblanks(&cp);
-
- // Convert char to lower case.
-
- c = *cp | 0x20;
-
- // Must start with a letter or a '/'.
-
- if ( (c < 'a' || c > 'z') && ( c != '/' ) )
- return 0;
-
- // Keep consuming characters until we hit a separator.
-
- while ( *cp && (*cp != '=') && (*cp != ' ') && (*cp != '\t') )
- cp++;
-
- // Only SPACE or TAB separator is accepted.
- // Reject everything else.
-
- if (*cp == '=')
- return 0;
-
- return 1;
-}
-
-//==========================================================================
-// Display the "boot:" prompt and copies the user supplied string to
-// kernBootStruct->bootString. The kernel image file name is written
-// to kernBootStruct->bootFile.
-
-static void
-getBootString()
-{
- char line[BOOT_STRING_LEN];
- char * cp;
- char * val;
- int count;
- static int timeout = kBootTimeout;
-
- do {
- line[0] = '\0';
- cp = &line[0];
-
- // If there were errors, don't timeout on boot prompt since
- // the same error is likely to occur again.
-
- if ( errors ) timeout = 0;
- errors = 0;
-
- // Print the boot prompt and wait a few seconds for user input.
-
- printf("\n");
- count = Gets(line, sizeof(line), timeout, "boot: ", "");
- flushdev();
-
- // If something was typed, don't use automatic boot again.
- // The boot: prompt will not timeout and go away until
- // the user hits the return key.
-
- if ( count ) timeout = 0;
-
- skipblanks(&cp);
-
- // If user typed '?', then display the usage message.
-
- if ( *cp == '?' )
- {
- showHelp();
- continue;
- }
-
- // Load config table file specified by the user, or fallback
- // to the default one.
-
- val = 0;
- getValueForBootKey(cp, "config", &val, &count);
- loadSystemConfig(val, count);
- if ( !sysConfigValid )
- continue;
- }
- while ( 0 );
-
- // Did the user specify a kernel file name at the boot prompt?
-
- if ( containsKernelName(cp) == 0 )
- {
- // User did not type a kernel image file name on the boot prompt.
- // This is fine, read the default kernel file name from the
- // config table.
-
- if ( getValueForKey(kKernelNameKey, &val, &count) )
- {
- strncpy(kernBootStruct->bootFile, val, count);
- }
- }
- else
- {
- // Get the kernel name from the user-supplied boot string,
- // and copy the name to the buffer provided.
-
- char * namep = kernBootStruct->bootFile;
-
- while ( *cp && !(*cp == ' ' || *cp == '\t') )
- *namep++ = *cp++;
-
- *namep = '\0';
- }
-
- // Verbose flag specified.
-
- gVerboseMode = getValueForBootKey(cp, "-v", &val, &count);
-
- // Save the boot string in kernBootStruct->bootString.
-
- if ( getValueForKey(kKernelFlagsKey, &val, &count) && count )
- {
- strncpy( kernBootStruct->bootString, val, count );
- }
- if ( strlen(cp) )
- {
- strcat(kernBootStruct->bootString, " ");
- strcat(kernBootStruct->bootString, cp);
- }
+
+ if (gUnloadPXEOnExit) nbpUnloadBaseCode();
}
#ifndef __BOOT2_BOOT_H
#define __BOOT2_BOOT_H
+#include "libsaio.h"
+
/*
* Keys used in system Default.table / Instance0.table
*/
#define kGraphicsModeKey "Graphics Mode"
+#define kTextModeKey "Text Mode"
#define kBootGraphicsKey "Boot Graphics"
#define kQuietBootKey "Quiet Boot"
#define kKernelFlagsKey "Kernel Flags"
#define kKernelNameKey "Kernel"
-/*
- * Possible values for the bootdev argument passed to boot().
- */
-enum {
- kBootDevHardDisk = 0,
- kBootDevFloppyDisk,
- kBootDevNetwork
-};
-
/*
* A global set by boot() to record the device that the booter
* was loaded from.
*/
-extern int gBootDev;
+extern int gBIOSDev;
+extern BOOL gBootGraphics;
+extern long gBootMode;
+extern BOOL sysConfigValid;
+extern char bootBanner[];
+extern char bootPrompt[];
+
+// Boot Modes
+enum {
+ kBootModeNormal = 0,
+ kBootModeSafe,
+ kBootModeSecure
+};
/*
* graphics.c
*/
-extern void message(char * str, int centered);
-extern void setMode(int mode);
-extern int currentMode();
+extern void printVBEInfo();
+extern void setVideoMode(int mode);
+extern int getVideoMode();
extern void spinActivityIndicator();
extern void clearActivityIndicator();
*/
extern long LoadDrivers(char * dirSpec);
+/*
+ * options.c
+ */
+extern void getBootOptions();
+extern int processBootOptions();
+
#endif /* !__BOOT2_BOOT_H */
#define data32 .byte 0x66
#define retf .byte 0xcb
-
.file "boot2.s"
+ .data
+
+EXPORT(_chainbootdev) .byte 0x80
+EXPORT(_chainbootflag) .byte 0x00
+
.text
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pushl %edx # bootdev
call _boot
+ testb $0xff, _chainbootflag
+ jnz start_chain_boot # Jump to a foreign booter
+
call __prot_to_real # Back to real mode.
data32
retf # Hardcode a far return
+start_chain_boot:
+ xorl %edx, %edx
+ movb _chainbootdev, %dl # Setup DL with the BIOS device number
+
+ call __prot_to_real # Back to real mode.
+
+ data32
+ call __switch_stack # Restore original stack
+
+ pop %es # Restore original ES and DS
+ pop %ds
+ popl %edi # Restore all general purpose registers
+ popl %esi # except EAX.
+ popl %ebp
+ popl %ebx
+ popl %ecx
+
+ data32
+ ljmp $0, $0x7c00 # Jump to boot code already in memory
* DRI: Josh de Cesare
*/
-#include "libsaio.h"
-#include "memory.h"
-#include "kernBootStruct.h"
-#include "nbp.h"
+#include "sl.h"
#include "boot.h"
enum {
};
typedef struct DriversPackage DriversPackage;
+enum {
+ kCFBundleType2,
+ kCFBundleType3
+};
+
static long FileLoadDrivers(char *dirSpec, long plugin);
static long NetLoadDrivers(char *dirSpec);
static long LoadDriverMKext(char *fileSpec);
-static long LoadDriverPList(char *dirSpec, char *name);
+static long LoadDriverPList(char *dirSpec, char *name, long bundleType);
static long LoadMatchedModules(void);
static long MatchPersonalities(void);
static long MatchLibraries(void);
static char * gExtensionsSpec;
static char * gDriverSpec;
static char * gFileSpec;
+static char * gTempSpec;
+static char * gFileName;
//==========================================================================
// BootX shim functions.
-#include <ufs/ufs/dir.h>
-
-#define kLoadAddr TFTP_ADDR
-#define kLoadSize TFTP_LEN
-
#define kPageSize 4096
#define RoundPage(x) ((((unsigned)(x)) + kPageSize - 1) & ~(kPageSize - 1))
-static long
-LoadFile( char * fileSpec )
-{
- unsigned long count = TFTP_LEN;
- unsigned long addr = TFTP_ADDR;
-
- if ( gBootDev == kBootDevNetwork )
- {
- if ( nbpTFTPReadFile(fileSpec, &count, addr) != nbpStatusSuccess )
- return -1;
- }
- else
- {
- int fd = open( fileSpec, 0 );
- if ( fd < 0 )
- return -1;
-
- count = read( fd, (char *) addr, count );
- close(fd);
- }
- return count;
-}
-
static long gImageFirstBootXAddr;
static long gImageLastKernelAddr;
if ( addr < gImageLastKernelAddr ) return 0;
- bzero(addr, size);
+ bzero((void *)addr, size);
gImageFirstBootXAddr = addr;
return 0;
}
-// Map BootX file types to UFS file types defined in ufs/ufs/dir.h.
-
-enum {
- kUnknownFileType = DT_UNKNOWN,
- kFlatFileType = DT_REG,
- kDirectoryFileType = DT_DIR,
- kLinkFileType = DT_LNK
-};
-
-static long
-GetFileInfo( char * dirSpec, char * name, long * flags, long * time )
-{
- struct dirstuff * dir;
- struct direct * entry = 0;
-
- dir = opendir(dirSpec);
- if ( dir )
- {
- while (( entry = readdir(dir) ))
- {
- if ( strcmp( entry->d_name, name ) == 0 )
- {
- *flags = entry->d_type;
- *time = 0;
- break;
- }
- }
- closedir(dir);
- }
- return ( entry ) ? 0 : -1;
-}
-
// Map BootX types to boot counterparts.
-#define gBootFileType gBootDev
+#define gBootFileType BIOS_DEV_TYPE(gBIOSDev)
enum {
- kNetworkDeviceType = kBootDevNetwork,
- kBlockDeviceType = kBootDevHardDisk
+ kNetworkDeviceType = kBIOSDevTypeNetwork,
+ kBlockDeviceType = kBIOSDevTypeHardDrive
};
-static struct dirstuff *
-OpenDir( char * dirSpec )
-{
- return opendir(dirSpec);
-}
-
-static void
-CloseDir( struct dirstuff * dirStuff )
-{
- closedir(dirStuff);
-}
-
-static long
-GetDirEntry( struct dirstuff * dir, long * dirIndex, char ** name,
- long * flags, long * time)
-{
- if ( dir )
- {
- struct direct * entry = readdir(dir);
-
- if ( entry )
- {
- *name = entry->d_name;
- *flags = entry->d_type;
- *time = 0;
- return 0;
- }
- }
- return (-1);
-}
static long
InitDriverSupport()
gExtensionsSpec = (char *) malloc( 4096 );
gDriverSpec = (char *) malloc( 4096 );
gFileSpec = (char *) malloc( 4096 );
+ gTempSpec = (char *) malloc( 4096 );
+ gFileName = (char *) malloc( 4096 );
- if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec )
- stop( "InitDriverSupport error" );
+ if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )
+ stop("InitDriverSupport error");
gImageLastKernelAddr = RoundPage( kernBootStruct->kaddr +
kernBootStruct->ksize );
#endif
MatchPersonalities();
-
+
MatchLibraries();
LoadMatchedModules();
static long
FileLoadDrivers( char * dirSpec, long plugin )
{
- long ret, length, index, flags, time;
- char * name;
- struct dirstuff * dir;
+ long ret, length, index, flags, time, bundleType;
+ const char * name;
if ( !plugin )
{
long time2;
ret = GetFileInfo(dirSpec, "Extensions.mkext", &flags, &time);
- if ((ret == 0) && (flags == kFlatFileType))
+ if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
{
ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
- if ((ret != 0) || (flags == kDirectoryFileType) || (time > time2))
+ if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeDirectory) ||
+ (((gBootMode & kBootModeSafe) == 0) && (time > time2)))
{
sprintf(gDriverSpec, "%sExtensions.mkext", dirSpec);
verbose("LoadDrivers: Loading from [%s]\n", gDriverSpec);
verbose("LoadDrivers: Loading from [%s]\n", dirSpec);
- // INTEL addition
- dir = OpenDir( dirSpec );
-
index = 0;
while (1) {
- // INTEL modification
- ret = GetDirEntry(dir, &index, &name, &flags, &time);
+ ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
if (ret == -1) break;
// Make sure this is a directory.
- if (flags != kDirectoryFileType) continue;
+ if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;
// Make sure this is a kext.
length = strlen(name);
if (strcmp(name + length - 5, ".kext")) continue;
+ // Save the file name.
+ strcpy(gFileName, name);
+
+ // Determine the bundle type.
+ sprintf(gTempSpec, "%s/%s", dirSpec, gFileName);
+ ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
+ if (ret == 0) bundleType = kCFBundleType2;
+ else bundleType = kCFBundleType3;
+
if (!plugin)
- sprintf(gDriverSpec, "%s/%s/Contents/PlugIns", dirSpec, name);
+ sprintf(gDriverSpec, "%s/%s/%sPlugIns", dirSpec, gFileName,
+ (bundleType == kCFBundleType2) ? "Contents/" : "");
- ret = LoadDriverPList(dirSpec, name);
+ ret = LoadDriverPList(dirSpec, gFileName, bundleType);
if (ret != 0)
{
// printf("LoadDrivers: failed\n");
ret = FileLoadDrivers(gDriverSpec, 1);
}
- // INTEL addition
- if ( dir ) CloseDir( dir );
-
return 0;
}
char segName[32];
DriversPackage * package = (DriversPackage *)kLoadAddr;
-#define GetPackageElement(e) bswap32(package-> ## e)
+#define GetPackageElement(e) NXSwapBigLongToHost(package->e)
// Load the MKext.
if (LoadFile(fileSpec) == -1) return -1;
// LoadDriverPList
static long
-LoadDriverPList( char * dirSpec, char * name )
+LoadDriverPList( char * dirSpec, char * name, long bundleType )
{
long length, driverPathLength;
ModulePtr module;
do {
// Save the driver path.
- sprintf(gFileSpec, "%s/%s/Contents/MacOS/", dirSpec, name);
+ sprintf(gFileSpec, "%s/%s/%s", dirSpec, name,
+ (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
driverPathLength = strlen(gFileSpec);
tmpDriverPath = malloc(driverPathLength + 1);
// Construct the file spec to the plist, then load it.
- sprintf(gFileSpec, "%s/%s/Contents/Info.plist", dirSpec, name);
+ sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name,
+ (bundleType == kCFBundleType2) ? "Contents/" : "");
length = LoadFile(gFileSpec);
if (length == -1) break;
* All rights reserved.
*/
-#include "libsaio.h"
#include "boot.h"
#include "vbe.h"
-#include "kernBootStruct.h"
-
-#define CHAR_W 8
-#define CHAR_W_SHIFT 3
-#define CHAR_H 16
-#define CHAR_H_SHIFT 4
-#define BYTE_SHIFT 3
-#define NCOLS (screen_width / CHAR_W)
-#define NROWS (screen_height / CHAR_H)
-#define SCREEN_W (screen_width)
-#define SCREEN_H (screen_height)
+#include "appleClut8.h"
+#include "happy_screen.h"
/*
- * Forward declarations.
+ * for spinning disk
*/
-static int convert_vbe_mode(char * mode_name, int * mode);
-BOOL gSilentBoot;
+static int currentIndicator = 0;
+
+static unsigned long lookUpCLUTIndex( unsigned char index,
+ unsigned char depth );
+
+static void drawColorRectangle( unsigned short x,
+ unsigned short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned char colorIndex );
+
+static void drawDataRectangle( unsigned short x,
+ unsigned short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned char * data );
+
+#define VIDEO(x) (kernBootStruct->video.v_ ## x)
+
//==========================================================================
-// Display a (optionally centered) text message.
+// printVBEInfo
-void
-message(char * str, int centered)
+void printVBEInfo()
+{
+ VBEInfoBlock vbeInfo;
+ int err;
+
+ // Fetch VBE Controller Info.
+
+ bzero( &vbeInfo, sizeof(vbeInfo) );
+ err = getVBEInfo( &vbeInfo );
+ if ( err != errSuccess )
+ return;
+
+ // Check presence of VESA signature.
+
+ if ( strncmp( vbeInfo.VESASignature, "VESA", 4 ) )
+ return;
+
+ // Announce controller properties.
+
+ printf("VESA v%d.%d %dMB (%s)\n",
+ vbeInfo.VESAVersion >> 8,
+ vbeInfo.VESAVersion & 0xf,
+ vbeInfo.TotalMemory / 16,
+ VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
+}
+
+//==========================================================================
+// getVESAModeWithProperties
+//
+// Return the VESA mode that matches the properties specified.
+// If a mode is not found, then return the "best" available mode.
+
+static unsigned short
+getVESAModeWithProperties( unsigned short width,
+ unsigned short height,
+ unsigned char bitsPerPixel,
+ unsigned short attributesSet,
+ unsigned short attributesClear,
+ VBEModeInfoBlock * outModeInfo )
{
- register int x;
+ VBEInfoBlock vbeInfo;
+ unsigned short * modePtr;
+ VBEModeInfoBlock modeInfo;
+ unsigned char modeBitsPerPixel;
+ unsigned short matchedMode = modeEndOfList;
+ int err;
+
+ // Clear output mode info.
- x = (NCOLS - strlen(str)) >> 1;
+ bzero( outModeInfo, sizeof(*outModeInfo) );
- if ( currentMode() == TEXT_MODE )
+ // Get VBE controller info containing the list of supported modes.
+
+ bzero( &vbeInfo, sizeof(vbeInfo) );
+ err = getVBEInfo( &vbeInfo );
+ if ( err != errSuccess )
+ {
+ return modeEndOfList;
+ }
+
+ // Loop through the mode list, and find the matching mode.
+
+ for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
+ *modePtr != modeEndOfList; modePtr++ )
{
- if (centered)
+ // Get mode information.
+
+ bzero( &modeInfo, sizeof(modeInfo) );
+ err = getVBEModeInfo( *modePtr, &modeInfo );
+ if ( err != errSuccess )
{
- while(x--) printf(" ");
+ continue;
}
- printf("%s\n", str);
- }
+
+#if 0 // debug
+ printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
+ *modePtr, modeInfo.XResolution, modeInfo.YResolution,
+ modeInfo.BitsPerPixel, modeInfo.MemoryModel,
+ modeInfo.ModeAttributes);
+#endif
+
+ // Filter out unwanted modes based on mode attributes.
+
+ if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
+ || ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
+ {
+ continue;
+ }
+
+ // Pixel depth in bits.
+
+ modeBitsPerPixel = modeInfo.BitsPerPixel;
+
+ if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
+ {
+ // Text mode, 16 colors.
+ }
+ else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
+ {
+ // Packed pixel, 256 colors.
+ }
+ else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
+ && ( modeInfo.MemoryModel == 6 )
+ && ( modeInfo.RedMaskSize == 5 )
+ && ( modeInfo.GreenMaskSize == 5 )
+ && ( modeInfo.BlueMaskSize == 5 ) )
+ {
+ // Direct color, 16 bpp (1:5:5:5).
+ modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
+ }
+ else if ( ( modeBitsPerPixel == 32 )
+ && ( modeInfo.MemoryModel == 6 )
+ && ( modeInfo.RedMaskSize == 8 )
+ && ( modeInfo.GreenMaskSize == 8 )
+ && ( modeInfo.BlueMaskSize == 8 ) )
+ {
+ // Direct color, 32 bpp (8:8:8:8).
+ }
+ else
+ {
+ continue; // Not a supported mode.
+ }
+
+ // Modes larger than the specified dimensions are skipped.
+
+ if ( ( modeInfo.XResolution > width ) ||
+ ( modeInfo.YResolution > height ) )
+ {
+ continue;
+ }
+
+ // Perfect match, we're done looking.
+
+ if ( ( modeInfo.XResolution == width ) &&
+ ( modeInfo.YResolution == height ) &&
+ ( modeBitsPerPixel == bitsPerPixel ) )
+ {
+ matchedMode = *modePtr;
+ bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
+ break;
+ }
+
+ // Save the next "best" mode in case a perfect match
+ // is not found.
+
+ if ( ( modeInfo.XResolution >= outModeInfo->XResolution ) &&
+ ( modeInfo.YResolution >= outModeInfo->YResolution ) &&
+ ( modeBitsPerPixel >= outModeInfo->BitsPerPixel ) )
+ {
+ matchedMode = *modePtr;
+ bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
+ }
+ }
+
+ return matchedMode;
}
-/*
- * for spinning disk
- */
-static int currentIndicator = 0;
+//==========================================================================
+// setupPalette
+
+static void setupPalette( VBEPalette * p, const unsigned char * g )
+{
+ int i;
+ unsigned char * source = (unsigned char *) g;
+
+ for (i = 0; i < 256; i++)
+ {
+ (*p)[i] = 0;
+ (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
+ (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
+ (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
+ }
+}
//==========================================================================
-// Set the screen mode: TEXT_MODE or GRAPHICS_MODE
+// setVESAGraphicsMode
-void
-setMode(int mode)
+static int
+setVESAGraphicsMode( unsigned short width,
+ unsigned short height,
+ unsigned char bitsPerPixel )
{
- unsigned int vmode;
- char * vmode_name;
- int err = errSuccess;
+ VBEModeInfoBlock minfo;
+ unsigned short mode;
+ int err = errFuncNotSupported;
+
+ do {
+ mode = getVESAModeWithProperties( width, height, bitsPerPixel,
+ maColorModeBit |
+ maModeIsSupportedBit |
+ maGraphicsModeBit |
+ maLinearFrameBufferAvailBit,
+ 0,
+ &minfo );
+ if ( mode == modeEndOfList )
+ {
+ break;
+ }
+
+ // Set the mode.
+
+ err = setVBEMode( mode | kLinearFrameBufferBit );
+ if ( err != errSuccess )
+ {
+ break;
+ }
+
+ // Set 8-bit color palette.
+
+ if ( minfo.BitsPerPixel == 8 )
+ {
+ VBEPalette palette;
+ setupPalette( &palette, appleClut8 );
+ if ((err = setVBEPalette(palette)) != errSuccess)
+ {
+ break;
+ }
+ }
+
+ // Is this required for buggy Video BIOS implementations?
+ // On which adapter?
+
+ if ( minfo.BytesPerScanline == 0 )
+ minfo.BytesPerScanline = ( minfo.XResolution *
+ minfo.BitsPerPixel ) >> 3;
- if ( currentMode() == mode ) return;
+ // Update KernBootStruct using info provided by the selected
+ // VESA mode.
- if ( mode == GRAPHICS_MODE &&
- (vmode_name = newStringForKey(kGraphicsModeKey)) != 0)
+ kernBootStruct->graphicsMode = GRAPHICS_MODE;
+ kernBootStruct->video.v_width = minfo.XResolution;
+ kernBootStruct->video.v_height = minfo.YResolution;
+ kernBootStruct->video.v_depth = minfo.BitsPerPixel;
+ kernBootStruct->video.v_rowBytes = minfo.BytesPerScanline;
+ kernBootStruct->video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
+ }
+ while ( 0 );
+
+ if ( err == errSuccess )
{
- // Set to the graphics mode specified in the config table file,
- // enable linear frame buffer mode, and update kernBootStruct.
+ char * happyScreen;
+ short * happyScreen16;
+ long * happyScreen32;
+ long cnt, x, y;
+
+ // Fill the background to white (same as BootX).
- if ( convert_vbe_mode(vmode_name, &vmode) == 0 )
- vmode = mode1024x768x256; /* default mode */
+ drawColorRectangle( 0, 0, minfo.XResolution, minfo.YResolution,
+ 0x00 /* color index */ );
- err = set_linear_video_mode(vmode);
+ // Prepare the data for the happy mac.
- if ( err == errSuccess )
+ switch ( VIDEO(depth) )
{
- kernBootStruct->graphicsMode = GRAPHICS_MODE;
- kernBootStruct->video.v_display = gSilentBoot;
- kernBootStruct->video.v_baseAddr = (unsigned long) frame_buffer;
- kernBootStruct->video.v_width = SCREEN_W;
- kernBootStruct->video.v_height = SCREEN_H;
- kernBootStruct->video.v_depth = bits_per_pixel;
- kernBootStruct->video.v_rowBytes = (screen_rowbytes == 0) ?
- (SCREEN_W * bits_per_pixel) >> BYTE_SHIFT : screen_rowbytes;
+ case 16 :
+ happyScreen16 = malloc(kHappyScreenWidth * kHappyScreenHeight * 2);
+ for (cnt = 0; cnt < (kHappyScreenWidth * kHappyScreenHeight); cnt++)
+ happyScreen16[cnt] = lookUpCLUTIndex(gHappyScreenPict[cnt], 16);
+ happyScreen = (char *) happyScreen16;
+ break;
+
+ case 32 :
+ happyScreen32 = malloc(kHappyScreenWidth * kHappyScreenHeight * 4);
+ for (cnt = 0; cnt < (kHappyScreenWidth * kHappyScreenHeight); cnt++)
+ happyScreen32[cnt] = lookUpCLUTIndex(gHappyScreenPict[cnt], 32);
+ happyScreen = (char *) happyScreen32;
+ break;
+
+ default :
+ happyScreen = (char *) gHappyScreenPict;
+ break;
}
- free(vmode_name);
+ x = ( VIDEO(width) - kHappyScreenWidth ) / 2;
+ y = ( VIDEO(height) - kHappyScreenHeight ) / 2 + kHappyScreenOffset;
+
+ // Draw the happy mac in the center of the display.
+
+ drawDataRectangle( x, y, kHappyScreenWidth, kHappyScreenHeight,
+ happyScreen );
+ }
+
+ return err;
+}
+
+//==========================================================================
+// LookUpCLUTIndex
+
+static unsigned long lookUpCLUTIndex( unsigned char index,
+ unsigned char depth )
+{
+ long result, red, green, blue;
+
+ red = appleClut8[index * 3 + 0];
+ green = appleClut8[index * 3 + 1];
+ blue = appleClut8[index * 3 + 2];
+
+ switch (depth) {
+ case 16 :
+ result = ((red & 0xF8) << 7) |
+ ((green & 0xF8) << 2) |
+ ((blue & 0xF8) >> 3);
+ result |= (result << 16);
+ break;
+
+ case 32 :
+ result = (red << 16) | (green << 8) | blue;
+ break;
+
+ default :
+ result = index | (index << 8);
+ result |= (result << 16);
+ break;
}
-
- if ( (mode == TEXT_MODE) || (err != errSuccess) )
+
+ return result;
+}
+
+//==========================================================================
+// drawColorRectangle
+
+static void * stosl(void * dst, long val, long len)
+{
+ asm( "rep; stosl"
+ : "=c" (len), "=D" (dst)
+ : "0" (len), "1" (dst), "a" (val)
+ : "memory" );
+
+ return dst;
+}
+
+static void drawColorRectangle( unsigned short x,
+ unsigned short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned char colorIndex )
+{
+ long pixelBytes;
+ long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
+ char * vram;
+
+ pixelBytes = VIDEO(depth) / 8;
+ vram = (char *) VIDEO(baseAddr) +
+ VIDEO(rowBytes) * y + pixelBytes * x;
+
+ while ( height-- )
{
- video_mode(2); // 80x25 text mode
-
- kernBootStruct->graphicsMode = TEXT_MODE;
- kernBootStruct->video.v_display = 0;
- kernBootStruct->video.v_baseAddr = (unsigned long) 0xb8000;
- kernBootStruct->video.v_width = 80;
- kernBootStruct->video.v_height = 25;
- kernBootStruct->video.v_depth = 8;
- kernBootStruct->video.v_rowBytes = 0x8000;
+ int rem = ( pixelBytes * width ) % 4;
+ if ( rem ) bcopy( &color, vram, rem );
+ stosl( vram + rem, color, pixelBytes * width / 4 );
+ vram += VIDEO(rowBytes);
}
+}
- currentIndicator = 0;
+//==========================================================================
+// drawDataRectangle
+
+static void drawDataRectangle( unsigned short x,
+ unsigned short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned char * data )
+{
+ long pixelBytes = VIDEO(depth) / 8;
+ char * vram = (char *) VIDEO(baseAddr) +
+ VIDEO(rowBytes) * y + pixelBytes * x;
+
+ while ( height-- )
+ {
+ bcopy( data, vram, width * pixelBytes );
+ vram += VIDEO(rowBytes);
+ data += width * pixelBytes;
+ }
}
//==========================================================================
-// Return the current screen mode, TEXT_MODE or GRAPHICS_MODE.
+// setVESATextMode
-int currentMode(void)
+static int
+setVESATextMode( unsigned short cols,
+ unsigned short rows,
+ unsigned char bitsPerPixel )
{
- return kernBootStruct->graphicsMode;
+ VBEModeInfoBlock minfo;
+ unsigned short mode = modeEndOfList;
+
+ if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
+ {
+ mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
+ maColorModeBit |
+ maModeIsSupportedBit,
+ maGraphicsModeBit,
+ &minfo );
+ }
+
+ if ( ( mode == modeEndOfList ) || ( setVBEMode(mode) != errSuccess ) )
+ {
+ video_mode( 2 ); // VGA BIOS, 80x25 text mode.
+ minfo.XResolution = 80;
+ minfo.YResolution = 25;
+ }
+
+ // Update KernBootStruct using info provided by the selected
+ // VESA mode.
+
+ kernBootStruct->graphicsMode = TEXT_MODE;
+ kernBootStruct->video.v_baseAddr = 0xb8000;
+ kernBootStruct->video.v_width = minfo.XResolution;
+ kernBootStruct->video.v_height = minfo.YResolution;
+ kernBootStruct->video.v_depth = 8;
+ kernBootStruct->video.v_rowBytes = 0x8000;
+
+ return errSuccess; // always return success
}
//==========================================================================
-// Convert from a string describing a graphics mode, to a VGA mode number.
-
-typedef struct {
- char mode_name[15];
- int mode_val;
-} mode_table_t;
-
-mode_table_t mode_table[] = {
- { "640x400x256", mode640x400x256 },
- { "640x480x256", mode640x480x256 },
- { "800x600x16", mode800x600x16 },
- { "800x600x256", mode800x600x256 },
- { "1024x768x16", mode1024x768x16 },
- { "1024x768x256", mode1024x768x256 },
- { "1280x1024x16", mode1280x1024x16 },
- { "1280x1024x256", mode1280x1024x256 },
- { "640x480x555", mode640x480x555 },
- { "640x480x888", mode640x480x888 },
- { "800x600x555", mode800x600x555 },
- { "800x600x888", mode800x600x888 },
- { "1024x768x555", mode1024x768x555 },
- { "1024x768x888", mode1024x768x888 },
- { "1280x1024x555", mode1280x1024x555 },
- { "1280x1024x888", mode1280x1024x888 },
- { "", 0 }
-};
-
-int convert_vbe_mode(char * mode_name, int * mode)
+// getNumberArrayFromProperty
+
+static int
+getNumberArrayFromProperty( const char * propKey,
+ unsigned long numbers[],
+ unsigned long maxArrayCount )
{
- mode_table_t * mtp = mode_table;
+ char * propStr;
+ int count = 0;
- if (mode_name == 0 || *mode_name == 0)
- return 0;
+#define _isdigit(c) ((c) >= '0' && (c) <= '9')
- while ( *mtp->mode_name )
+ propStr = newStringForKey( (char *) propKey );
+ if ( propStr )
{
- if (strcmp(mtp->mode_name, mode_name) == 0)
+ char * delimiter = propStr;
+
+ while ( count < maxArrayCount && *propStr != '\0' )
{
- *mode = mtp->mode_val;
- return 1;
+ unsigned long val = strtoul( propStr, &delimiter, 10 );
+ if ( propStr != delimiter )
+ {
+ numbers[count++] = val;
+ propStr = delimiter;
+ }
+ while ( ( *propStr != '\0' ) && !_isdigit(*propStr) )
+ propStr++;
}
- mtp++;
+
+ free( propStr );
}
- return 0;
+
+ return count;
+}
+
+//==========================================================================
+// setVideoMode
+//
+// Set the video mode to TEXT_MODE or GRAPHICS_MODE.
+
+void
+setVideoMode( int mode )
+{
+ unsigned long params[3];
+ int count;
+ int err = errSuccess;
+
+ if ( mode == GRAPHICS_MODE )
+ {
+ count = getNumberArrayFromProperty( kGraphicsModeKey, params, 3 );
+ if ( count < 3 )
+ {
+ params[0] = 1024; // Default graphics mode is 1024x768x16.
+ params[1] = 768;
+ params[2] = 16;
+ }
+
+ // Map from pixel format to bits per pixel.
+
+ if ( params[2] == 256 ) params[2] = 8;
+ if ( params[2] == 555 ) params[2] = 16;
+ if ( params[2] == 888 ) params[2] = 32;
+
+ err = setVESAGraphicsMode( params[0], params[1], params[2] );
+ if ( err == errSuccess )
+ {
+ // If this boolean is set to true, then the console driver
+ // in the kernel will show the animated color wheel on the
+ // upper left corner.
+
+ kernBootStruct->video.v_display = !gVerboseMode;
+ }
+ }
+
+ if ( (mode == TEXT_MODE) || (err != errSuccess) )
+ {
+ count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
+ if ( count < 2 )
+ {
+ params[0] = 80; // Default text mode is 80x25.
+ params[1] = 25;
+ }
+
+ setVESATextMode( params[0], params[1], 4 );
+ kernBootStruct->video.v_display = 0;
+ }
+
+ currentIndicator = 0;
+}
+
+//==========================================================================
+// Return the current video mode, TEXT_MODE or GRAPHICS_MODE.
+
+int getVideoMode(void)
+{
+ return kernBootStruct->graphicsMode;
}
//==========================================================================
else
lastTickTime = currentTickTime;
- if ( currentMode() == TEXT_MODE )
+ if ( getVideoMode() == TEXT_MODE )
{
string[0] = indicator[currentIndicator];
printf(string);
void
clearActivityIndicator( void )
{
- if ( currentMode() == TEXT_MODE )
+ if ( getVideoMode() == TEXT_MODE )
{
printf(" \b");
}
--- /dev/null
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * happy_screen.h - Picture displayed a the beginning of the boot process
+ *
+ * Copyright (c) 2002 Apple Computer, Inc.
+ *
+ * DRI: Josh de Cesare
+ */
+
+#define kHappyScreenWidth (52)
+#define kHappyScreenHeight (44)
+#define kHappyScreenOffset (-44)
+
+static const unsigned char gHappyScreenPict[] =
+{
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x12,0x27,0xf7,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0xf7,0x27,0x12,0x00,0x00,
+ 0x00,0x12,0x37,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x37,0x12,0x00,
+ 0x00,0x27,0x50,0x43,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x43,0x50,0x27,0x00,
+ 0x00,0xf7,0x50,0x20,0xa3,0x33,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x33,0xa3,0x20,0x50,0xf7,0x00,
+ 0x00,0x50,0x50,0x00,0x33,0x33,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x33,0x33,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x37,0x3c,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x37,0x3c,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x55,0x55,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x55,0x55,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x4d,0x50,0x0d,0x00,0x00,0x00,0x12,0x33,0x09,0x00,0x00,0x00,0x00,0x0b,0x4d,0x50,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x15,0x01,0x00,0x00,0x07,0x4d,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x50,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x50,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x50,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x50,0x37,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc0,0x27,0x17,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x50,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x50,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x50,0x33,0xa3,0x00,0x00,0x00,0x00,0xa3,0x33,0x50,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x2f,0x50,0x33,0x1b,0x0a,0x0a,0x1b,0x33,0x50,0x2f,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x2f,0x50,0x50,0x50,0x50,0x50,0x50,0x2f,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x43,0x43,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x4d,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x4d,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x00,0x33,0x33,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x33,0x33,0x00,0x50,0x50,0x00,
+ 0x00,0x50,0x50,0x20,0xa3,0x33,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x33,0xa3,0x20,0x50,0x50,0x00,
+ 0x00,0x27,0x50,0x43,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x43,0x50,0x27,0x00,
+ 0x00,0x12,0x37,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x37,0x12,0x00,
+ 0x00,0x00,0x12,0x27,0xf7,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0xf7,0x27,0x12,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
--- /dev/null
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License"). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "boot.h"
+#include "fdisk.h"
+
+enum {
+ kReturnKey = 0x0d,
+ kEscapeKey = 0x1b,
+ kBackspaceKey = 0x08,
+ kASCIIKeyMask = 0x7f
+};
+
+enum {
+ kMenuTopRow = 5,
+ kMenuMaxItems = 6,
+ kScreenLastRow = 24
+};
+
+static BVRef gBootVolume = 0;
+
+static void showHelp();
+
+//==========================================================================
+
+enum {
+ kCursorTypeHidden = 0x0100,
+ kCursorTypeUnderline = 0x0607
+};
+
+typedef struct {
+ int x;
+ int y;
+ int type;
+} CursorState;
+
+static void changeCursor( int col, int row, int type, CursorState * cs )
+{
+ if (cs) getCursorPositionAndType( &cs->x, &cs->y, &cs->type );
+ setCursorType( type );
+ setCursorPosition( col, row, 0 );
+}
+
+static void moveCursor( int col, int row )
+{
+ setCursorPosition( col, row, 0 );
+}
+
+static void restoreCursor( const CursorState * cs )
+{
+ setCursorPosition( cs->x, cs->y, 0 );
+ setCursorType( cs->type );
+}
+
+//==========================================================================
+
+static void flushKeyboardBuffer()
+{
+ while ( readKeyboardStatus() ) getc();
+}
+
+//==========================================================================
+
+static int countdown( const char * msg, int row, int timeout )
+{
+ int time;
+ int ch = 0;
+ int col = strlen(msg) + 1;
+
+ flushKeyboardBuffer();
+
+ moveCursor( 0, row );
+ printf(msg);
+
+ for ( time = time18(), timeout++; timeout; )
+ {
+ if (ch = readKeyboardStatus())
+ break;
+
+ if ( time18() >= time )
+ {
+ time += 18;
+ timeout--;
+ moveCursor( col, row );
+ printf("(%d) ", timeout);
+ }
+ }
+
+ flushKeyboardBuffer();
+
+ return ch;
+}
+
+//==========================================================================
+
+static char gBootArgs[BOOT_STRING_LEN];
+static char * gBootArgsPtr = gBootArgs;
+static char * gBootArgsEnd = gBootArgs + BOOT_STRING_LEN - 1;
+
+static void clearBootArgs()
+{
+ gBootArgsPtr = gBootArgs;
+ memset( gBootArgs, '\0', BOOT_STRING_LEN );
+}
+
+//==========================================================================
+
+static void showBootPrompt( int row, BOOL visible )
+{
+ extern char bootPrompt[];
+
+ changeCursor( 0, row, kCursorTypeUnderline, 0 );
+ clearScreenRows( row, kScreenLastRow );
+ clearBootArgs();
+
+ if ( visible )
+ {
+ printf( bootPrompt );
+ }
+ else
+ {
+ printf("Press Return to start up the foreign OS. ");
+ }
+}
+
+//==========================================================================
+
+static void updateBootArgs( int key )
+{
+ key &= kASCIIKeyMask;
+
+ switch ( key )
+ {
+ case kBackspaceKey:
+ if ( gBootArgsPtr > gBootArgs )
+ {
+ int x, y, t;
+ getCursorPositionAndType( &x, &y, &t );
+ if ( x == 0 && y )
+ {
+ x = 80; y--;
+ }
+ if (x) x--;
+ setCursorPosition( x, y, 0 );
+ putca(' ', 0x07, 1);
+ *gBootArgsPtr-- = '\0';
+ }
+ break;
+
+ default:
+ if ( key >= ' ' && gBootArgsPtr < gBootArgsEnd)
+ {
+ putchar(key); // echo to screen
+ *gBootArgsPtr++ = key;
+ }
+ break;
+ }
+}
+
+//==========================================================================
+
+typedef struct {
+ char name[80];
+ void * param;
+} MenuItem;
+
+static const MenuItem * gMenuItems = NULL;
+static int gMenuItemCount;
+static int gMenuRow;
+static int gMenuHeight;
+static int gMenuTop;
+static int gMenuBottom;
+static int gMenuSelection;
+
+static void printMenuItem( const MenuItem * item, int highlight )
+{
+ printf(" ");
+
+ if ( highlight )
+ putca(' ', 0x70, strlen(item->name) + 4);
+ else
+ putca(' ', 0x07, 40);
+
+ printf(" %40s\n", item->name);
+}
+
+//==========================================================================
+
+static void showMenu( const MenuItem * items, int count,
+ int selection, int row, int height )
+{
+ int i;
+ CursorState cursorState;
+
+ if ( items == NULL || count == 0 ) return;
+
+ // head and tail points to the start and the end of the list.
+ // top and bottom points to the first and last visible items
+ // in the menu window.
+
+ gMenuItems = items;
+ gMenuRow = row;
+ gMenuHeight = height;
+ gMenuItemCount = count;
+ gMenuTop = 0;
+ gMenuBottom = min( count, height ) - 1;
+ gMenuSelection = selection;
+
+ // If the selected item is not visible, shift the list down.
+
+ if ( gMenuSelection > gMenuBottom )
+ {
+ gMenuTop += ( gMenuSelection - gMenuBottom );
+ gMenuBottom = gMenuSelection;
+ }
+
+ // Draw the visible items.
+
+ changeCursor( 0, row, kCursorTypeHidden, &cursorState );
+
+ for ( i = gMenuTop; i <= gMenuBottom; i++ )
+ {
+ printMenuItem( &items[i], (i == gMenuSelection) );
+ }
+
+ restoreCursor( &cursorState );
+}
+
+//==========================================================================
+
+static int updateMenu( int key, void ** paramPtr )
+{
+ int moved = 0;
+
+ union {
+ struct {
+ unsigned int
+ selectionUp : 1,
+ selectionDown : 1,
+ scrollUp : 1,
+ scrollDown : 1;
+ } f;
+ unsigned int w;
+ } draw = {{0}};
+
+ if ( NULL == gMenuItems ) return 0;
+
+ // Look at the scan code.
+
+ switch ( key )
+ {
+ case 0x4800: // Up Arrow
+ if ( gMenuSelection != gMenuTop )
+ draw.f.selectionUp = 1;
+ else if ( gMenuTop > 0 )
+ draw.f.scrollDown = 1;
+ break;
+
+ case 0x5000: // Down Arrow
+ if ( gMenuSelection != gMenuBottom )
+ draw.f.selectionDown = 1;
+ else if ( gMenuBottom < (gMenuItemCount - 1) )
+ draw.f.scrollUp = 1;
+ break;
+ }
+
+ if ( draw.w )
+ {
+ if ( draw.f.scrollUp )
+ {
+ scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1);
+ gMenuTop++; gMenuBottom++;
+ draw.f.selectionDown = 1;
+ }
+
+ if ( draw.f.scrollDown )
+ {
+ scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1);
+ gMenuTop--; gMenuBottom--;
+ draw.f.selectionUp = 1;
+ }
+
+ if ( draw.f.selectionUp || draw.f.selectionDown )
+ {
+ CursorState cursorState;
+
+ // Set cursor at current position, and clear inverse video.
+
+ changeCursor( 0, gMenuRow + gMenuSelection - gMenuTop,
+ kCursorTypeHidden, &cursorState );
+
+ printMenuItem( &gMenuItems[gMenuSelection], 0 );
+
+ if ( draw.f.selectionUp ) gMenuSelection--;
+ else gMenuSelection++;
+
+ moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop );
+
+ printMenuItem( &gMenuItems[gMenuSelection], 1 );
+
+ restoreCursor( &cursorState );
+ }
+
+ *paramPtr = gMenuItems[gMenuSelection].param;
+ moved = 1;
+ }
+
+ return moved;
+}
+
+//==========================================================================
+
+static void skipblanks( const char ** cpp )
+{
+ while ( **(cpp) == ' ' || **(cpp) == '\t' ) ++(*cpp);
+}
+
+//==========================================================================
+
+static const char * extractKernelName( char ** cpp )
+{
+ char * kn = *cpp;
+ char * cp = *cpp;
+ char c;
+
+ // Convert char to lower case.
+
+ c = *cp | 0x20;
+
+ // Must start with a letter or a '/'.
+
+ if ( (c < 'a' || c > 'z') && ( c != '/' ) )
+ return 0;
+
+ // Keep consuming characters until we hit a separator.
+
+ while ( *cp && (*cp != '=') && (*cp != ' ') && (*cp != '\t') )
+ cp++;
+
+ // Only SPACE or TAB separator is accepted.
+ // Reject everything else.
+
+ if (*cp == '=')
+ return 0;
+
+ // Overwrite the separator, and move the pointer past
+ // the kernel name.
+
+ if (*cp != '\0') *cp++ = '\0';
+ *cpp = cp;
+
+ return kn;
+}
+
+//==========================================================================
+
+void getBootOptions()
+{
+ int i;
+ int key;
+ int selectIndex = 0;
+ int bvCount;
+ int nextRow;
+ BVRef bvr;
+ BVRef bvChain;
+ BVRef menuBVR;
+ BOOL showPrompt, newShowPrompt;
+ MenuItem * menuItems = NULL;
+ static BOOL firstRun = YES;
+
+ clearBootArgs();
+ clearScreenRows( kMenuTopRow, kScreenLastRow );
+ changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
+ printf("Scanning device %x...", gBIOSDev);
+
+ // Get a list of bootable volumes on the device.
+
+ bvChain = scanBootVolumes( gBIOSDev, &bvCount );
+ gBootVolume = menuBVR = selectBootVolume( bvChain );
+
+#if 0
+ // When booting from CD (via HD emulation), default to hard
+ // drive boot when possible.
+
+ if ( gBootVolume->part_type == FDISK_BOOTER &&
+ gBootVolume->biosdev == 0x80 )
+ {
+ // Scan the original device 0x80 that has been displaced
+ // by the CD-ROM.
+
+ BVRef hd_bvr = selectBootVolume(scanBootVolumes(0x81, 0));
+ if ( hd_bvr->flags & kBVFlagNativeBoot )
+ {
+ int key = countdown("Press C to start up from CD-ROM.",
+ kMenuTopRow, 5);
+
+ if ( (key & 0x5f) != 'c' )
+ {
+ gBootVolume = hd_bvr;
+ gBIOSDev = hd_bvr->biosdev;
+ initKernBootStruct( gBIOSDev );
+ goto done;
+ }
+ }
+ }
+#endif
+
+ // Allow user to override default setting.
+
+ if ( firstRun &&
+ countdown("Press any key to enter startup options.",
+ kMenuTopRow, 3) == 0 )
+ {
+ goto done;
+ }
+
+ if ( bvCount )
+ {
+ // Allocate memory for an array of menu items.
+
+ menuItems = (MenuItem *) malloc( sizeof(MenuItem) * bvCount );
+ if ( menuItems == NULL ) goto done;
+
+ // Associate a menu item for each BVRef.
+
+ for ( bvr = bvChain, i = bvCount - 1, selectIndex = 0;
+ bvr; bvr = bvr->next, i-- )
+ {
+ getBootVolumeDescription( bvr, menuItems[i].name, 80 );
+ menuItems[i].param = (void *) bvr;
+ if ( bvr == menuBVR ) selectIndex = i;
+ }
+ }
+
+ // Clear screen and hide the blinking cursor.
+
+ clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
+ changeCursor( 0, kMenuTopRow, kCursorTypeHidden, 0 );
+ nextRow = kMenuTopRow;
+ showPrompt = YES;
+
+ // Show the menu.
+
+ if ( bvCount )
+ {
+ printf("Use \30\31 keys to select the startup volume.");
+ showMenu( menuItems, bvCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
+ nextRow += min( bvCount, kMenuMaxItems ) + 3;
+ }
+
+ // Show the boot prompt.
+
+ showPrompt = (bvCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
+ showBootPrompt( nextRow, showPrompt );
+
+ do {
+ key = getc();
+
+ updateMenu( key, (void **) &menuBVR );
+
+ newShowPrompt = (bvCount == 0) ||
+ (menuBVR->flags & kBVFlagNativeBoot);
+
+ if ( newShowPrompt != showPrompt )
+ {
+ showPrompt = newShowPrompt;
+ showBootPrompt( nextRow, showPrompt );
+ }
+ if ( showPrompt ) updateBootArgs( key );
+
+ switch ( key & kASCIIKeyMask )
+ {
+ case kReturnKey:
+ if ( *gBootArgs == '?' )
+ {
+ showHelp(); key = 0;
+ showBootPrompt( nextRow, showPrompt );
+ break;
+ }
+ gBootVolume = menuBVR;
+ break;
+
+ case kEscapeKey:
+ clearBootArgs();
+ break;
+
+ default:
+ key = 0;
+ }
+ }
+ while ( 0 == key );
+
+done:
+ firstRun = NO;
+
+ clearScreenRows( kMenuTopRow, kScreenLastRow );
+ changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
+
+ if ( menuItems ) free(menuItems);
+}
+
+//==========================================================================
+
+extern unsigned char chainbootdev;
+extern unsigned char chainbootflag;
+
+int processBootOptions()
+{
+ KERNBOOTSTRUCT * kbp = kernBootStruct;
+ const char * cp = gBootArgs;
+ const char * val = 0;
+ const char * kernel;
+ int cnt;
+
+ skipblanks( &cp );
+
+ // Update the unit and partition number.
+
+ if ( gBootVolume )
+ {
+ if ( gBootVolume->flags & kBVFlagForeignBoot )
+ {
+ readBootSector( gBootVolume->biosdev, gBootVolume->part_boff,
+ (void *) 0x7c00 );
+
+ //
+ // Setup edx, and signal intention to chain load the
+ // foreign booter.
+ //
+
+ chainbootdev = gBootVolume->biosdev;
+ chainbootflag = 1;
+
+ return 1;
+ }
+
+ kbp->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) |
+ (B_PARTITIONMASK << B_PARTITIONSHIFT));
+
+ kbp->kernDev |= MAKEKERNDEV( 0,
+ /* unit */ BIOS_DEV_UNIT(gBootVolume->biosdev),
+ /* partition */ gBootVolume->part_no );
+ }
+
+ // Load config table specified by the user, or use the default.
+
+ getValueForBootKey( cp, "config", &val, &cnt );
+ loadSystemConfig(val, cnt);
+ if ( !sysConfigValid ) return -1;
+
+ // Use the kernel name specified by the user, or fetch the name
+ // in the config table.
+
+ if (( kernel = extractKernelName((char **)&cp) ))
+ {
+ strcpy( kbp->bootFile, kernel );
+ }
+ else
+ {
+ if ( getValueForKey( kKernelNameKey, &val, &cnt ) )
+ strncpy( kbp->bootFile, val, cnt );
+ }
+
+ // Store the merged kernel flags and boot args.
+
+ getValueForKey( kKernelFlagsKey, &val, &cnt );
+ if ( (strlen(cp) + 1 + cnt) < BOOT_STRING_LEN )
+ {
+ if (cnt) strncpy(kbp->bootString, val, cnt);
+ sprintf(&kbp->bootString[cnt], "%s%s", cnt ? " " : "", cp);
+ }
+
+ gVerboseMode = getValueForKey( "-v", &val, &cnt ) ||
+ getValueForKey( "-s", &val, &cnt );
+
+ gBootGraphics = getBoolForKey( kBootGraphicsKey );
+
+ gBootMode = ( getValueForKey( "-f", &val, &cnt ) ) ?
+ kBootModeSafe : kBootModeNormal;
+
+ return 0;
+}
+
+//==========================================================================
+// Load the help file and display the file contents on the screen.
+
+static void showHelp()
+{
+#define BOOT_HELP_PATH "/usr/standalone/i386/BootHelp.txt"
+
+ int fd;
+
+ if ( (fd = open(BOOT_HELP_PATH, 0)) >= 0 )
+ {
+ char * buffer;
+
+ // Activate and clear page 1
+ // Perhaps this should be loaded only once?
+
+ setActiveDisplayPage(1);
+ clearScreenRows(0, 24);
+ setCursorPosition( 0, 0, 1 );
+
+ buffer = malloc( file_size(fd) );
+ read(fd, buffer, file_size(fd) - 1);
+ close(fd);
+ printf("%s", buffer);
+ free(buffer);
+
+ // Wait for a keystroke and return to page 0.
+
+ getc();
+ setActiveDisplayPage(0);
+ }
+}
#include "vers.h"
-char bootPrompt[] = "\n\nDarwin/x86 boot v" I386BOOT_VERSION "\n"
- "%dK conventional / %dK extended memory\n\n"
- "Darwin/x86 will start up in %d seconds, or you can:\n"
- " Type -v and press Return to start up Darwin/x86 with "
- "diagnostic messages\n"
- " Type ? and press Return to learn about advanced startup "
- "options\n"
- " Type any other character to stop Darwin/x86 from "
- "starting up automatically\n";
+char bootBanner[] = "\nDarwin/x86 boot v" I386BOOT_VERSION "\n"
+ "%dK conventional / %dK extended memory\n";
+
+char bootPrompt[] =
+ "Press Return to start up Darwin/x86 with no options, or you can:\n"
+ " Type -v and press Return to start up with diagnostic messages\n"
+ " Type ? and press Return to learn about advanced startup options\n\n"
+ "boot: ";
INSTALL_MD_DIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/machdep/i386
OPTIM = -Os
-CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Wno-precomp \
- -munaligned-text -static -traditional-cpp
+CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
+ -fno-builtin -static
INC = -I. -I$(SYMROOT) -I$(UTILDIR)
ifneq "" "$(wildcard /bin/mkdirs)"
SA_OBJS = prf.o printf.o zalloc.o \
string.o strtol.o error.o \
- setjmp.o qsort.o bswap.o
+ setjmp.o qsort.o
SFILES = setjmp.s
CFILES = prf.c printf.c zalloc.c \
string.c strtol.c error.c \
- qsort.c bswap.c
+ qsort.c
HFILES = memory.h
EXPORTED_HFILES = libsa.h kernBootStruct.h memory.h
INSTALLED_SA_HFILES = libsa.h
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include "libsa.h"
-
-unsigned long bswap32( unsigned long data )
-{
- __asm__ volatile("bswap %0"
- : "=r" (data)
- : "0" (data));
- return data;
-}
* string.c
*/
#ifndef bcopy
-extern void bcopy(const void * src, void * dst, int len);
+extern void bcopy(const void * src, void * dst, size_t len);
#endif
#ifndef bzero
-extern void bzero(void * dst, int len);
+extern void bzero(void * dst, size_t len);
#endif
extern void * memset(void * dst, int c, size_t n);
extern char * strcpy(char * s1, const char * s2);
extern char * strncpy(char * s1, const char * s2, size_t n);
extern int atoi(const char * str);
-extern int ptol(char * str);
+extern int ptol(const char * str);
+extern int strlen(const char * str);
extern char * strcat(char * s1, const char * s2);
extern char * strncat(char * s1, const char * s2, size_t n);
/*
* strtol.c
*/
-extern long strtol(const char * nptr,
- char ** endptr,
- int base);
-
-extern unsigned long strtoul(const char * nptr,
- char ** endptr,
- int base);
+extern long strtol(const char * nptr, char ** endptr, int base);
+extern unsigned long strtoul(const char * nptr, char ** endptr, int base);
/*
* prf.c
*/
-extern void prf(const char * fmt,
- va_list ap,
- void (*putfn_p)(),
- void * putfn_arg);
+extern void prf(const char * fmt, va_list ap, void (*putfn_p)(),
+ void * putfn_arg);
/*
* printf.c
*/
extern int sprintf(char *s, const char * format, ...);
-extern int slvprintf(char * buffer,
- int len,
- const char * fmt,
- va_list arg);
+extern int slvprintf(char * buffer, int len, const char * fmt, va_list arg);
/*
* zalloc.c
* getsegbyname.c
*/
extern struct segment_command *
- getsegbynamefromheader(struct mach_header * mhp, char * segname);
-
-/*
- * bswap.c
- */
-extern unsigned long bswap32( unsigned long data );
+ getsegbynamefromheader(struct mach_header * mhp, char * segname);
#endif /* !__BOOT_LIBSA_H */
/* Memory addresses used by booter and friends */
+#define BASE_SEG 0x2000
+#define STACK_SEG 0x3000
+#define STACK_OFS 0xFFF0 // stack pointer
+
+#define BOOT2_SEG BASE_SEG
+#define BOOT2_OFS 0x0200 // 512 byte disk sector offset
+
+#define BIOS_ADDR 0x0C00 // BIOS disk I/O buffer
+#define BIOS_LEN 0x2400 // 9K
+
/* These are all "virtual" addresses...
* which are physical addresses plus MEMBASE.
*/
-
-#define MEMBASE 0x0
-#define BASE_SEG 0x0
-
-#define BIOS_ADDR 0x000C00 // BIOS buffer
-#define BIOS_LEN 0x002400 // 9k
-#define BOOTER_LOAD_ADDR 0x003000 // loaded here for compat.
-#define BOOTER_ADDR 0x003000 // start of booter code
-#define BOOTER_LEN 0x00B000
-#define STACK_ADDR 0x00FFF0
-#define BOOTSTRUCT_ADDR 0x011000 // it's slightly smaller
-#define BOOTSTRUCT_LEN 0x00F000
-#define RLD_ADDR 0x030000 // not used
-#define RLD_LEN 0x070000
-#define VIDEO_ADDR 0x0A0000 // unusable space
-#define VIDEO_LEN 0x060000
-#define KERNEL_ADDR 0x100000 // 14Mb kernel + drivers
-#define KERNEL_LEN 0xe00000
-#define ZALLOC_ADDR 0xf00000 // 1Mb for zalloc
-#define ZALLOC_LEN 0x100000
-#define TFTP_ADDR 0x1000000 // 8Mb download buffer
-#define TFTP_LEN 0x800000
-
-/* These are physical values */
-
-#define CONVENTIONAL_LEN 0x0A0000 // 640k
-#define EXTENDED_ADDR 0x100000 // 1024k
-#define KERNEL_BOOT_ADDR KERNEL_ADDR // load at 1Mb
-
-#define ptov(paddr) ((paddr) - MEMBASE)
-#define vtop(vaddr) ((vaddr) + MEMBASE)
+#define ADDR32(seg, ofs) (((seg) << 4 ) + (ofs))
+
+#define MEMBASE 0x0
+
+#define BOOTSTRUCT_ADDR 0x011000 // it's slightly smaller
+#define BOOTSTRUCT_LEN 0x00F000
+
+#define BASE_ADDR ADDR32(BASE_SEG, 0)
+#define BOOT2_ADDR ADDR32(BOOT2_SEG, BOOT2_OFS)
+
+#define VIDEO_ADDR 0x0A0000 // unusable space
+#define VIDEO_LEN 0x060000
+
+#define KERNEL_ADDR 0x100000 // 15M kernel + drivers
+#define KERNEL_LEN 0xF00000
+
+#define ZALLOC_ADDR 0x1000000 // 4M zalloc area
+#define ZALLOC_LEN 0x400000
+
+#define LOAD_ADDR 0x01400000 // File download buffer
+#define LOAD_LEN 0x800000 // Max file size
+
+#define TFTP_ADDR LOAD_ADDR // tftp download buffer
+#define TFTP_LEN LOAD_LEN
+
+#define kLoadAddr LOAD_ADDR
+#define kLoadSize LOAD_LEN
+
+#define CONVENTIONAL_LEN 0x0A0000 // 640k
+#define EXTENDED_ADDR 0x100000 // 1024k
+
+#define ptov(paddr) ((paddr) - MEMBASE)
+#define vtop(vaddr) ((vaddr) + MEMBASE)
+
+/*
+ * Extract segment/offset from a linear address.
+ */
+#define OFFSET16(addr) ((addr) - BASE_ADDR)
+#define OFFSET(addr) ((addr) & 0xFFFF)
+#define SEGMENT(addr) (((addr) & 0xF0000) >> 4)
+
+/*
+ * We need a minimum of 32MB of system memory.
+ */
+#define MIN_SYS_MEM_KB (32 * 1024)
/*
- * Limits to the size of various things...
+ * The number of descriptor entries in the GDT.
*/
+#define NGDTENT 7
/*
- * We need a minimum of 24Mb of system memory.
+ * The total size of the GDT in bytes.
+ * Each descriptor entry require 8 bytes.
*/
-#define MIN_SYS_MEM_KB (24 * 1024)
+#define GDTLIMIT ( NGDTENT * 8 )
#endif /* !__BOOT_MEMORY_H */
return dst;
}
-void bcopy(const void * src, void * dst, int len)
+void bcopy(const void * src, void * dst, size_t len)
{
memcpy(dst, src, len);
}
-void bzero(void * dst, int len)
+void bzero(void * dst, size_t len)
{
memset(dst, 0, len);
}
}
int
-ptol(char *str)
+ptol(const char *str)
{
register int c = *str;
SYMROOT=
OPTIM = -Os
-CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Wno-precomp \
- -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER -munaligned-text -static \
- -traditional-cpp -DRCZ_COMPRESSED_FILE_SUPPORT
+CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
+ -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER -fno-builtin -static \
+ -DRCZ_COMPRESSED_FILE_SUPPORT
DEFINES=
CONFIG = hd
INC = -I../rcz -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I/System/Library/Frameworks/System.framework/PrivateHeaders
VPATH = $(OBJROOT):$(SYMROOT)
-SAIO_OBJS = table.o asm.o biosfn.o misc.o gets.o \
- vga.o disk.o sys.o cache.o \
- ufs_byteorder.o bootstruct.o \
- stringTable.o load.o \
- bios.o pci.o vbe.o nbp.o
+SAIO_OBJS = table.o asm.o bios.o biosfn.o \
+ disk.o sys.o cache.o bootstruct.o \
+ ufs.o ufs_byteorder.o \
+ stringTable.o load.o misc.o \
+ vbe.o nbp.o hfs.o hfs_compare.o
SAIO_EXTERN_OBJS = console.o
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __LIBSAIO_APPLECLUT8_H
-#define __LIBSAIO_APPLECLUT8_H
-
-static const unsigned char appleClut8[ 256 * 3 ] = {
-
- 0x00,0x00,0x00, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66,
- 0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC,
- 0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00,
- 0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66,
- 0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC,
- 0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00,
- 0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66,
- 0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC,
- 0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00,
- 0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66,
- 0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC,
- 0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00,
- 0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66,
- 0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC,
- 0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00,
- 0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66,
-
-
- 0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC,
- 0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00,
- 0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66,
- 0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC,
- 0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00,
- 0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66,
- 0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC,
- 0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00,
- 0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66,
- 0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC,
- 0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00,
- 0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66,
- 0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC,
- 0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00,
- 0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66,
- 0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC,
- 0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00,
-
-
- 0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66,
- 0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC,
- 0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00,
- 0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66,
- 0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC,
- 0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00,
- 0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66,
- 0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC,
- 0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00,
- 0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66,
- 0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC,
- 0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00,
- 0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66,
- 0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC,
- 0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00,
- 0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66,
-
-
- 0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC,
- 0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00,
- 0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66,
- 0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC,
- 0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00,
- 0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00,
- 0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00,
- 0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00,
- 0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00,
- 0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE,
- 0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88,
- 0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22,
- 0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB,
- 0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55,
- 0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0xFF,0xFF,0xFF
-};
-
-#endif /* !__LIBSAIO_APPLECLUT8_H */
/*
* HISTORY
* $Log: asm.s,v $
+ * Revision 1.3 2002/07/09 14:06:21 jliu
+ * Merging changes from PR-2954224 branch in boot/i386.
+ *
+ * Revision 1.2.30.1 2002/07/05 16:24:51 jliu
+ * Merged UFS/HFS/HFS+ filesystem support from BootX.
+ * Moved boot2 load address due to increased size. boot0/boot1 also changed.
+ * Updated boot graphics and CLUT.
+ * Added support to chain load foreign booters.
+ * Fixed param passing bug in network loader.
+ * Misc cleanup in libsaio.
+ *
* Revision 1.2 2000/05/23 23:01:11 lindak
* Merged PR-2309530 into Kodiak (liu i386 booter: does not support label-less
* ufs partitions)
* Import of boot-25 (~mwatson)
*
* Revision 2.1.1.2 90//03//22 17:59:50 rvb
- * Added _sp() => where is the stack at. [kupfer]
+ * Added _sp() => where is the stack at. [kupfer]
*
* Revision 2.1.1.1 90//02//09 17:25:04 rvb
- * Add Intel copyright
- * [90//02//09 rvb]
+ * Add Intel copyright
+ * [90//02//09 rvb]
*
*/
.file "asm.s"
-BOOTSEG = BASE_SEG
+CR0_PE_ON = 0x1
+CR0_PE_OFF = 0x7ffffffe
-CR0_PE_ON = 0x1
-CR0_PE_OFF = 0xfffffffe
+STACK32_BASE = ADDR32(STACK_SEG, 0)
+STACK16_SEG = STACK_SEG
+CODE32_BASE = ADDR32(BASE_SEG, 0)
+CODE16_SEG = BASE_SEG
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Pointer to 6-bytes in memory that contains the base address and the limit
+// (size of GDT table in bytes) of the GDT. The LGDT is the only instruction
+// that directly loads a linear address (not a segment relative address) and
+// a limit in protected mode.
.globl _Gdtr
.data
- .align 2,0x90
+ .align 2, 0x90
_Gdtr:
- .word 0x2F
-// .long _Gdt+4096
+ .word GDTLIMIT
.long vtop(_Gdt)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Data area for __switch_stack.
//
-save_sp: .long STACK_ADDR
-save_ss: .long 0
-
+save_sp: .long STACK_OFS
+save_ss: .long STACK_SEG
.text
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// real_to_prot()
-// transfer from real mode to protected mode.
-// preserves all registers except eax
+//
+// Transfer from real mode to protected mode.
+// Preserves all registers except EAX.
//
LABEL(__real_to_prot)
- // guarantee that interrupt is disabled when in prot mode
+
+ // Interrupts are disabled in protected mode.
+
cli
- addr32 // load the gdtr
+ // Load the Global Descriptor Table Register (GDTR).
+
+ addr32
data32
- lgdt _Gdtr
+ lgdt OFFSET16(_Gdtr)
- // set the PE bit of CR0 to go to protected mode
+ // Enter protected mode by setting the PE bit in CR0.
mov %cr0, %eax
data32
or $CR0_PE_ON, %eax
- mov %eax, %cr0
+ mov %eax, %cr0
- // make intrasegment jump to flush the processor pipeline and
- // reload CS register
+ // Make intrasegment jump to flush the processor pipeline and
+ // reload CS register.
data32
ljmp $0x08, $xprot
xprot:
// we are in USE32 mode now
- // set up the protected mode segment registers : DS, SS, ES
+ // set up the protected mode segment registers : DS, SS, ES, FS, GS
mov $0x10, %eax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ // Convert STACK_SEG:SP to 32-bit linear stack pointer.
- xorl %eax, %eax // clear garbage from upper word of esp
- movw %sp, %ax
+ movzwl %sp, %eax
+ addl $STACK32_BASE, %eax
movl %eax, %esp
+ // Convert STACK_SEG:BP to 32-bit linear base pointer.
+
+ movzwl %bp, %eax
+ addl $STACK32_BASE, %eax
+ movl %eax, %ebp
+
+ // Modify the caller's return address on the stack from
+ // segment offset to linear address.
+
+ popl %eax
+ addl $CODE32_BASE, %eax
+ pushl %eax
+
ret
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// prot_to_real()
-// transfer from protected mode to real mode
-// preserves all registers except eax
+//
+// Transfer from protected mode to real mode.
+// Preserves all registers except EAX.
//
LABEL(__prot_to_real)
+ // Set up segment registers appropriate for real mode.
+
+ movw $0x30, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
ljmp $0x18, $x16 // change to USE16 mode
x16:
// and reload CS register
data32
- ljmp $BOOTSEG, $xreal
+ ljmp $CODE16_SEG, $xreal - CODE32_BASE
xreal:
// we are in real mode now
- // set up the real mode segment registers : DS, SS, ES
+ // set up the real mode segment registers : DS, DS, ES, FS, GS
movw %cs, %ax
movw %ax, %ds
- movw %ax, %ss
movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ // load stack segment register SS.
data32
- ret
+ movl $STACK16_SEG, %eax
+ movw %ax, %ss
-#if defined(DEFINE_INLINE_FUNCTIONS)
+ // clear top 16-bits of ESP and EBP.
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// outb(port, byte)
-//
-LABEL(_outb)
- push %ebp
- mov %esp, %ebp
- push %edx
+ data32
+ movzwl %sp, %esp
+ data32
+ movzwl %bp, %ebp
- movw 8(%ebp), %dx
- movb 12(%ebp), %al
- outb %al, %dx
+ // Modify caller's return address on the stack
+ // from linear address to segment offset.
- pop %edx
- pop %ebp
- ret
+ data32
+ popl %eax
+ data32
+ movzwl %ax, %eax
+ data32
+ pushl %eax
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// inb(port)
-//
-LABEL(_inb)
- push %ebp
- mov %esp, %ebp
- push %edx
+ // Reenable maskable interrupts.
- movw 8(%ebp), %dx
- subw %ax, %ax
- inb %dx, %al
+ sti
- pop %edx
- pop %ebp
+ data32
ret
-#endif /* DEFINE_INLINE_FUNCTIONS */
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// halt()
//
LABEL(_halt)
-// call _getchar
hlt
jmp _halt
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// startprog(phyaddr)
-// Start the program on protected mode where phyaddr is the entry point
+// Start the program on protected mode where phyaddr is the entry point.
//
LABEL(_startprog)
push %ebp
mov %esp, %ebp
- mov 0x8(%ebp), %ecx // entry offset
- mov $0x28, %ebx // segment
+ mov 0x8(%ebp), %ecx // entry offset
+ mov $0x28, %ebx // segment
push %ebx
push %ecx
ret
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Returns the current stack pointer.
+// Returns the current frame pointer.
//
LABEL(__bp)
mov %ebp, %eax
ret
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Switch stack.
-# Switches between registers SS:SP and memory save_ss:save_sp.
-# Call this function from real mode only!!!
-#
-# AX, DI, and SI are modified.
-#
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// switch_stack()
+//
+// Switches stack pointer between SS:SP and memory save_ss:save_sp.
+// Call this function from real mode only!!!
+//
+// AX, DI, and SI are clobbered.
+//
LABEL(__switch_stack)
- popl %eax # save return address
- popl %edi # discard upper 16-bit
-
- data32
- addr32
- movl save_ss, %esi # copy new SS to ESI
-
- data32
- addr32
- movl save_sp, %edi # copy new SP to EDI
-
- addr32
- mov %ss, save_ss # save current SS
-
- data32
- addr32
- movl %esp, save_sp # Save current SP
-
- cli
- mov %si, %ss # Perform stack switch
- mov %di, %sp
- sti
-
- pushl %eax # push IP of caller onto the new stack
-
- xorl %eax, %eax
- xorl %esi, %esi
- xorl %edi, %edi
-
- ret
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Issue a request to the network loader.
-#
+ popl %eax # save return address
+ popl %edi # discard upper 16-bit
+
+ data32
+ addr32
+ movl OFFSET16(save_ss), %esi # new SS to SI
+
+ data32
+ addr32
+ movl OFFSET16(save_sp), %edi # new SP to DI
+
+ addr32
+ mov %ss, OFFSET16(save_ss) # save current SS to memory
+
+ data32
+ addr32
+ movl %esp, OFFSET16(save_sp) # save current SP to memory
+
+ cli
+ mov %si, %ss # switch stack
+ mov %di, %sp
+ sti
+
+ pushl %eax # push IP of caller onto the new stack
+
+ xorl %eax, %eax
+ xorl %esi, %esi
+ xorl %edi, %edi
+
+ ret
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// loader()
+//
+// Issue a request to the network loader.
+//
LABEL(_loader)
- enter $0, $0
- pushal
+ enter $0, $0
+ pushal
+
+ #
+ # Pass a far pointer to the command structure
+ # to the INT call through DX:CX.
+ #
+ # The command code is in BX.
+ #
+
+ movw 8(%ebp), %bx # 8[EBP] = command code
+ movw 12(%ebp), %cx # 12[EBP] = command structure offset
+ movw 14(%ebp), %dx # 14[EBP] = command structure segment
- #
- # Pass a far pointer to the command structure
- # to the INT call through DI:CX.
- #
- # The command code is in BX.
- #
+ call __prot_to_real # Revert to real mode
- movw 8(%ebp), %bx # 8[EBP] = command code
- movw 12(%ebp), %cx # 12[EBP] = command structure offset
- movw 14(%ebp), %di # 14[EBP] = command structure segment
+ ###### Real Mode Begin ######
- call __prot_to_real # Revert to real mode
+ data32
+ call __switch_stack # Switch to NBP stack
- ###### Real Mode Begin ######
+ int $0x2b # Call NBP
- data32
- call __switch_stack # Switch to NBP stack
+ data32
+ call __switch_stack # Restore stack
- int $0x2b # Call NBP
+ data32
+ call __real_to_prot # Back to protected mode
- data32
- call __switch_stack # Restore stack
+ ###### Real Mode End ######
- data32
- call __real_to_prot # Back to protected mode
-
- ###### Real Mode End ######
-
- popal
- leave
- ret
+ popal
+ leave
+ ret
#if 0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
machineFlags_t flags;
} biosBuf_t;
+#define EBIOS_FIXED_DISK_ACCESS 0x01
+#define EBIOS_ENHANCED_DRIVE_INFO 0x04
+extern unsigned char uses_ebios[];
+
#endif /* !__LIBSAIO_BIOS_H */
* Harness for calling real-mode BIOS functions.
*/
-#include "legacy/asm.h"
-
-#define data32 .byte 0x66
-#define addr32 .byte 0x67
-
-#define O_INT 0
-#define O_EAX 4
-#define O_EBX 8
-#define O_ECX 12
-#define O_EDX 16
-#define O_EDI 20
-#define O_ESI 24
-#define O_EBP 28
-#define O_CS 32
-#define O_DS 34
-#define O_ES 36
-#define O_FLG 38
+#include <architecture/i386/asm_help.h>
+#include "memory.h"
+
+#define data32 .byte 0x66
+#define addr32 .byte 0x67
+
+#define O_INT 0
+#define O_EAX 4
+#define O_EBX 8
+#define O_ECX 12
+#define O_EDX 16
+#define O_EDI 20
+#define O_ESI 24
+#define O_EBP 28
+#define O_CS 32
+#define O_DS 34
+#define O_ES 36
+#define O_FLG 38
.data
- .lcomm save_eax, 4,2
- .lcomm save_edx, 4,2
- .lcomm save_es, 2,1
- .lcomm save_flag, 2,1
- .lcomm new_eax, 4,2
- .lcomm new_edx, 4,2
- .lcomm new_es, 2,1
+ .lcomm save_eax, 4,2
+ .lcomm save_edx, 4,2
+ .lcomm save_es, 2,1
+ .lcomm save_flag, 2,1
+ .lcomm new_eax, 4,2
+ .lcomm new_edx, 4,2
+ .lcomm new_es, 2,1
.text
* Call real-mode BIOS INT functions.
*
*/
-ENTRY(bios)
- enter $0,$0
- pushal
-
- movl 8(%ebp), %edx // address of save area
- movb O_INT(%edx), %al // save int number
- movb %al, do_int+1
-
- movl O_EBX(%edx), %ebx
- movl O_ECX(%edx), %ecx
- movl O_EDI(%edx), %edi
- movl O_ESI(%edx), %esi
- movl O_EBP(%edx), %ebp
- movl %edx, save_edx
- movl O_EAX(%edx), %eax
- movl %eax, new_eax
- movl O_EDX(%edx), %eax
- movl %eax, new_edx
- movw O_ES(%edx), %ax
- movl %ax, new_es
-
- call EXT(_prot_to_real)
-
- data32
- addr32
- mov new_eax, %eax
- data32
- addr32
- mov new_edx, %edx
- data32
- addr32
- mov new_es, %es
+LABEL(_bios)
+ enter $0, $0
+ pushal
+
+ movl 8(%ebp), %edx // address of save area
+ movb O_INT(%edx), %al // save int number
+ movb %al, do_int+1
+
+ movl O_EBX(%edx), %ebx
+ movl O_ECX(%edx), %ecx
+ movl O_EDI(%edx), %edi
+ movl O_ESI(%edx), %esi
+ movl O_EBP(%edx), %ebp
+ movl %edx, save_edx
+ movl O_EAX(%edx), %eax
+ movl %eax, new_eax
+ movl O_EDX(%edx), %eax
+ movl %eax, new_edx
+ movw O_ES(%edx), %ax
+ movl %ax, new_es
+
+ call __prot_to_real
+
+ data32
+ addr32
+ mov OFFSET16(new_eax), %eax
+ data32
+ addr32
+ mov OFFSET16(new_edx), %edx
+ data32
+ addr32
+ mov OFFSET16(new_es), %es
do_int:
- int $0x00
- pushf
- data32
- addr32
- movl %eax, save_eax
- popl %eax // actually pop %ax
- addr32
- movl %eax, save_flag // actually movw
- mov %es, %ax
- addr32
- movl %eax, save_es // actually movw
- data32
- call EXT(_real_to_prot)
-
- movl %edx, new_edx // save new edx before clobbering
- movl save_edx, %edx
- movl new_edx, %eax // now move it into buffer
- movl %eax, O_EDX(%edx)
- movl save_eax, %eax
- movl %eax, O_EAX(%edx)
- movw save_es, %ax
- movw %ax, O_ES(%edx)
- movw save_flag, %ax
- movw %ax, O_FLG(%edx)
- movl %ebx, O_EBX(%edx)
- movl %ecx, O_ECX(%edx)
- movl %edi, O_EDI(%edx)
- movl %esi, O_ESI(%edx)
- movl %ebp, O_EBP(%edx)
-
- popal
- leave
-
- ret
-
+ int $0x00
+ pushf
+ data32
+ addr32
+ movl %eax, OFFSET16(save_eax)
+ popl %eax // actually pop %ax
+ addr32
+ movl %eax, OFFSET16(save_flag) // actually movw
+ mov %es, %ax
+ addr32
+ movl %eax, OFFSET16(save_es) // actually movw
+ data32
+ call __real_to_prot
+
+ movl %edx, new_edx // save new edx before clobbering
+ movl save_edx, %edx
+ movl new_edx, %eax // now move it into buffer
+ movl %eax, O_EDX(%edx)
+ movl save_eax, %eax
+ movl %eax, O_EAX(%edx)
+ movw save_es, %ax
+ movw %ax, O_ES(%edx)
+ movw save_flag, %ax
+ movw %ax, O_FLG(%edx)
+ movl %ebx, O_EBX(%edx)
+ movl %ecx, O_ECX(%edx)
+ movl %edi, O_EDI(%edx)
+ movl %esi, O_ESI(%edx)
+ movl %ebp, O_EBP(%edx)
+
+ popal
+ leave
+
+ ret
+
/*============================================================================
* Determines the total system memory size using various BIOS Int 15 calls.
*
*/
-ENTRY(get_memsize)
- enter $0, $0 # create frame pointer (32 bit operand/stack)
- pushal # save all registers
-
- movl 8(%ebp), %ebx # push input structure pointer to stack
- pushl %ebx
-
- call EXT(_prot_to_real) # switch to real mode
-
- ##################################################################
- # In real mode.
- # Do not forget the opcode overrides, since the assembler
- # does not know we have made a transition to 16-bit operation.
- ##################################################################
-
- data32
- movl $0xE801, %eax # Get memory size
- clc
- int $0x15
- data32
- jnc getmsz_e801
-
- data32
- movl $0xDA88, %eax # Get memory size
- clc
- int $0x15
- data32
- jnc getmsz_da88
-
- movb $0x8A, %ah # Get memory size
- clc
- int $0x15
- data32
- jnc getmsz_8a
-
- movb $0x88, %ah # Get memory size
- clc
- int $0x15
- data32
- jnc getmsz_88
-
- xorl %edx, %edx # Error, cannot get memory size
- xorl %eax, %eax
+LABEL(_get_memsize)
+ enter $0, $0 # create frame pointer (32 bit operand/stack)
+ pushal # save all registers
+
+ movl 8(%ebp), %ebx # push input structure pointer to stack
+ pushl %ebx
+
+ call __prot_to_real # switch to real mode
+
+ ##################################################################
+ # In real mode.
+ # Do not forget the opcode overrides, since the assembler
+ # does not know we have made a transition to 16-bit operation.
+ ##################################################################
+
+ data32
+ movl $0xE801, %eax # Get memory size
+ clc
+ int $0x15
+ data32
+ jnc getmsz_e801
+
+ data32
+ movl $0xDA88, %eax # Get memory size
+ clc
+ int $0x15
+ data32
+ jnc getmsz_da88
+
+ movb $0x8A, %ah # Get memory size
+ clc
+ int $0x15
+ data32
+ jnc getmsz_8a
+
+ movb $0x88, %ah # Get memory size
+ clc
+ int $0x15
+ data32
+ jnc getmsz_88
+
+ xorl %edx, %edx # Error, cannot get memory size
+ xorl %eax, %eax
getmsz_done:
- data32
- addr32
- pushl %eax # Push EAX to 32-bit stack
+ data32
+ addr32
+ pushl %eax # Push EAX to 32-bit stack
- data32
- call EXT(_real_to_prot) # Back to protected mode. EAX is modified.
+ data32
+ call __real_to_prot # Back to protected mode. EAX is modified.
- ##################################################################
- # Back to protected mode.
- ##################################################################
+ ##################################################################
+ # Back to protected mode.
+ ##################################################################
- popl %eax # Pop EAX from stack
- popl %ebx # Pop pointer to register structure
+ popl %eax # Pop EAX from stack
+ popl %ebx # Pop pointer to register structure
- # Copy the result to the input structure pointed to by a pointer
- # which is on top of the stack. Write register EAX and EDX to the
- # structure.
+ # Copy the result to the input structure pointed to by a pointer
+ # which is on top of the stack. Write register EAX and EDX to the
+ # structure.
- movl %eax, O_EAX(%ebx)
- movl %edx, O_EDX(%ebx)
+ movl %eax, O_EAX(%ebx)
+ movl %edx, O_EDX(%ebx)
- popal # restore all registers
- leave # undo enter operator
- ret
+ popal # restore all registers
+ leave # undo enter operator
+ ret
getmsz_88:
- orl %eax, %eax
- data32
- jz getmsz_64m
- xorl %edx, %edx
+ orl %eax, %eax
+ data32
+ jz getmsz_64m
+ xorl %edx, %edx
getmsz_8a:
- data32
- movl $1024, %ebx # Add in 1M
- addl %ebx, %eax
- adcl $0, %edx
- data32
- jmp getmsz_done
+ data32
+ movl $1024, %ebx # Add in 1M
+ addl %ebx, %eax
+ adcl $0, %edx
+ data32
+ jmp getmsz_done
getmsz_64m:
- data32
- movl $1, %edx
- xorl %eax, %eax
- data32
- jmp getmsz_done
+ data32
+ movl $1, %edx
+ xorl %eax, %eax
+ data32
+ jmp getmsz_done
getmsz_da88:
- xor %dh, %dh
- movb %cl, %dl
- movl %ebx, %eax
- data32
- jmp getmsz_8a
+ xor %dh, %dh
+ movb %cl, %dl
+ movl %ebx, %eax
+ data32
+ jmp getmsz_8a
getmsz_e801:
- xorl %edx, %edx
- orl %ebx, %ebx
- data32
- jz getmsz_88
-
- data32
- movl $64, %eax
- mul %ebx
-
- data32
- movl $16384, %ebx
- addl %ebx, %eax
- adcl $0, %edx
-
- data32
- jmp getmsz_done
+ xorl %edx, %edx
+ orl %ebx, %ebx
+ data32
+ jz getmsz_88
+
+ data32
+ movl $64, %eax
+ mul %ebx
+
+ data32
+ movl $16384, %ebx
+ addl %ebx, %eax
+ adcl $0, %edx
+
+ data32
+ jmp getmsz_done
*/
#include "libsaio.h"
-#include "memory.h"
-#include "kernBootStruct.h"
static biosBuf_t bb;
unsigned char uses_ebios[8] = {0, 0, 0, 0, 0, 0, 0, 0};
bb.eax.r.h = 0x01;
bios(&bb);
if (bb.flags.zf) {
- return 0;
+ return 0;
} else {
- return bb.eax.rr;
+ return bb.eax.rr;
}
}
unsigned int time18(void)
{
union {
- struct {
- unsigned int low:16;
- unsigned int high:16;
- } s;
- unsigned int i;
+ struct {
+ unsigned int low:16;
+ unsigned int high:16;
+ } s;
+ unsigned int i;
} time;
bb.intno = 0x1a;
int i;
bb.intno = 0x13;
- sec += 1; /* sector numbers start at 1 */
+ sec += 1; /* sector numbers start at 1 */
for (i=0;;) {
- bb.ecx.r.h = cyl;
- bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F);
- bb.edx.r.h = head;
- bb.edx.r.l = dev;
- bb.eax.r.l = num;
- bb.ebx.rr = ptov(BIOS_ADDR);
- bb.es = ((unsigned long)&i & 0xffff0000) >> 4;
-
- bb.eax.r.h = 0x02;
- bios(&bb);
+ bb.ecx.r.h = cyl;
+ bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F);
+ bb.edx.r.h = head;
+ bb.edx.r.l = dev;
+ bb.eax.r.l = num;
+ bb.ebx.rr = OFFSET(ptov(BIOS_ADDR));
+ bb.es = SEGMENT(ptov(BIOS_ADDR));
+
+ bb.eax.r.h = 0x02;
+ bios(&bb);
- if ((bb.eax.r.h == 0x00) || (i++ >= 5))
- break;
+ if ((bb.eax.r.h == 0x00) || (i++ >= 5))
+ break;
- /* reset disk subsystem and try again */
- bb.eax.r.h = 0x00;
- bios(&bb);
+ /* reset disk subsystem and try again */
+ bb.eax.r.h = 0x00;
+ bios(&bb);
}
return bb.eax.r.h;
}
int ebiosread(int dev, long sec, int count)
{
int i;
- struct {
- unsigned char size;
- unsigned char reserved;
- unsigned char numblocks;
- unsigned char reserved2;
- unsigned int buffer;
- unsigned long long startblock;
+ 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 = {0};
addrpacket.size = sizeof(addrpacket);
for (i=0;;) {
- bb.intno = 0x13;
+ bb.intno = 0x13;
bb.eax.r.h = 0x42;
bb.edx.r.l = dev;
- bb.esi.rr = ((unsigned)&addrpacket & 0xffff);
- addrpacket.numblocks = count;
- addrpacket.buffer = ptov(BIOS_ADDR);
- addrpacket.startblock = sec;
+ bb.esi.rr = OFFSET((unsigned)&addrpacket);
+ bb.ds = 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;
void putc(int ch)
{
bb.intno = 0x10;
- bb.ebx.r.h = 0x00; /* background black */
- bb.ebx.r.l = 0x0F; /* foreground white */
+ bb.ebx.r.h = 0x00; /* background black */
+ bb.ebx.r.l = 0x0F; /* foreground white */
bb.eax.r.h = 0x0e;
bb.eax.r.l = ch;
bios(&bb);
}
+void putca(int ch, int attr, int repeat)
+{
+ bb.intno = 0x10;
+ bb.ebx.r.h = 0x00; /* page number */
+ bb.ebx.r.l = attr; /* attribute */
+ bb.eax.r.h = 0x9;
+ bb.eax.r.l = ch;
+ bb.ecx.rx = repeat; /* repeat count */
+ bios(&bb);
+}
+
unsigned int get_diskinfo(int drive)
{
- struct {
+ static struct {
unsigned short size;
unsigned short flags;
unsigned long cylinders;
unsigned char useEbios = 0;
union {
- compact_diskinfo_t di;
- unsigned int ui;
+ compact_diskinfo_t di;
+ unsigned int ui;
} ret;
static int maxhd = 0;
ret.ui = 0;
if (maxhd == 0) {
- bb.intno = 0x13;
- bb.eax.r.h = 0x08;
- bb.edx.r.l = 0x80;
- bios(&bb);
- if (bb.flags.cf == 0)
- maxhd = 0x7f + bb.edx.r.l;
+ bb.intno = 0x13;
+ bb.eax.r.h = 0x08;
+ bb.edx.r.l = 0x80;
+ bios(&bb);
+ if (bb.flags.cf == 0)
+ maxhd = 0x7f + bb.edx.r.l;
};
if (drive > maxhd)
- return 0;
+ return 0;
/* Check drive for EBIOS support. */
bb.intno = 0x13;
bb.ebx.rr = 0x55aa;
bios(&bb);
if(bb.ebx.rr == 0xaa55 && bb.flags.cf == 0) {
+ /* Get flags for supported operations. */
+ useEbios = bb.ecx.r.l;
+ }
+ if (useEbios & EBIOS_ENHANCED_DRIVE_INFO) {
/* Get EBIOS drive info. */
ebios.size = 26;
bb.intno = 0x13;
bb.eax.r.h = 0x48;
bb.edx.r.l = drive;
- bb.esi.rr = ((unsigned)&ebios & 0xffff);
+ bb.esi.rr = OFFSET((unsigned)&ebios);
+ bb.ds = SEGMENT((unsigned)&ebios);
bios(&bb);
- if(bb.flags.cf == 0 && ebios.cylinders != 0) {
- useEbios = 1;
+ if(bb.flags.cf != 0) {
+ useEbios = 0;
}
}
hds = bb.edx.r.h;
sec = bb.ecx.r.l & 0x3F;
- if(useEbios) {
+ if(useEbios & EBIOS_ENHANCED_DRIVE_INFO) {
cyl = (ebios.total_sectors / ((hds + 1) * sec)) - 1;
}
else {
return ret.ui;
}
-void setCursorPosition(int x, int y)
+void setCursorPosition(int x, int y, int page)
{
bb.intno = 0x10;
bb.eax.r.h = 0x02;
- bb.ebx.r.h = 0x00; /* page 0 for graphics */
+ bb.ebx.r.h = page; /* page 0 for graphics */
bb.edx.r.l = x;
bb.edx.r.h = y;
bios(&bb);
}
+void setCursorType(int type)
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = 0x01;
+ bb.ecx.rr = type;
+ bios(&bb);
+}
+
+void getCursorPositionAndType(int * x, int * y, int * type)
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = 0x03;
+ bios(&bb);
+ *x = bb.edx.r.l;
+ *y = bb.edx.r.h;
+ *type = bb.ecx.rr;
+}
+
+void scollPage(int x1, int y1, int x2, int y2, int attr, int rows, int dir)
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = (dir > 0) ? 0x06 : 0x07;
+ bb.eax.r.l = rows;
+ bb.ebx.r.h = attr;
+ bb.ecx.r.h = y1;
+ bb.ecx.r.l = x1;
+ bb.edx.r.h = y2;
+ bb.edx.r.l = x2;
+ bios(&bb);
+}
+
+void clearScreenRows( int y1, int y2 )
+{
+ scollPage( 0, y1, 80 - 1, y2, 0x07, y2 - y1 + 1, 1 );
+}
+
+void setActiveDisplayPage( int page )
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = 5;
+ bb.eax.r.l = page;
+ bios(&bb);
+}
+
#if DEBUG
+int terminateDiskEmulation()
+{
+ static char cd_spec[0x12];
+
+ bb.intno = 0x13;
+ bb.eax.r.h = 0x4b;
+ bb.eax.r.l = 0; // subfunc: terminate emulation
+ bb.esi.rr = OFFSET((unsigned)&cd_spec);
+ bb.ds = SEGMENT((unsigned)&cd_spec);
+ bios(&bb);
+ return bb.eax.r.h;
+}
+
int readDriveParameters(int drive, struct driveParameters *dp)
{
bb.intno = 0x13;
bb.eax.r.h = 0x08;
bios(&bb);
if (bb.eax.r.h == 0) {
- dp->heads = bb.edx.r.h;
- dp->sectors = bb.ecx.r.l & 0x3F;
- dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
- dp->totalDrives = bb.edx.r.l;
+ dp->heads = bb.edx.r.h;
+ dp->sectors = bb.ecx.r.l & 0x3F;
+ dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
+ dp->totalDrives = bb.edx.r.l;
} else {
- bzero(dp, sizeof(*dp));
+ bzero(dp, sizeof(*dp));
}
return bb.eax.r.h;
}
#endif
-#define APM_INTNO 0x15
-#define APM_INTCODE 0x53
+#define APM_INTNO 0x15
+#define APM_INTCODE 0x53
int
APMPresent(void)
bb.ebx.rr = 0x0000;
bios(&bb);
if ((bb.flags.cf == 0) &&
- (bb.ebx.r.h == 'P') &&
- (bb.ebx.r.l == 'M')) {
- /* Success */
- kbp->apmConfig.major_vers = bb.eax.r.h;
- kbp->apmConfig.minor_vers = bb.eax.r.l;
- kbp->apmConfig.flags.data = bb.ecx.rr;
- return 1;
+ (bb.ebx.r.h == 'P') &&
+ (bb.ebx.r.l == 'M')) {
+ /* Success */
+ kbp->apmConfig.major_vers = bb.eax.r.h;
+ kbp->apmConfig.minor_vers = bb.eax.r.l;
+ kbp->apmConfig.flags.data = bb.ecx.rr;
+ return 1;
}
return 0;
}
bb.ebx.rr = 0x0000;
bios(&bb);
if (bb.flags.cf == 0) {
- /* Success */
- kbp->apmConfig.cs32_base = (bb.eax.rr) << 4;
- kbp->apmConfig.entry_offset = bb.ebx.rx;
- kbp->apmConfig.cs16_base = (bb.ecx.rr) << 4;
- kbp->apmConfig.ds_base = (bb.edx.rr) << 4;
- if (kbp->apmConfig.major_vers >= 1 &&
- kbp->apmConfig.minor_vers >= 1) {
- kbp->apmConfig.cs_length = bb.esi.rr;
- kbp->apmConfig.ds_length = bb.edi.rr;
- } else {
- kbp->apmConfig.cs_length =
- kbp->apmConfig.ds_length = 64 * 1024;
- }
- kbp->apmConfig.connected = 1;
- return 1;
+ /* Success */
+ kbp->apmConfig.cs32_base = (bb.eax.rr) << 4;
+ kbp->apmConfig.entry_offset = bb.ebx.rx;
+ kbp->apmConfig.cs16_base = (bb.ecx.rr) << 4;
+ kbp->apmConfig.ds_base = (bb.edx.rr) << 4;
+ if (kbp->apmConfig.major_vers >= 1 &&
+ kbp->apmConfig.minor_vers >= 1) {
+ kbp->apmConfig.cs_length = bb.esi.rr;
+ kbp->apmConfig.ds_length = bb.edi.rr;
+ } else {
+ kbp->apmConfig.cs_length =
+ kbp->apmConfig.ds_length = 64 * 1024;
+ }
+ kbp->apmConfig.connected = 1;
+ return 1;
}
return 0;
}
-#ifdef EISA_SUPPORT // turn off for now since there isn't enough room
+#ifdef EISA_SUPPORT
BOOL
eisa_present(
void
)
{
- static BOOL checked;
- static BOOL isEISA;
+ static BOOL checked;
+ static BOOL isEISA;
if (!checked) {
- if (strncmp((char *)0xfffd9, "EISA", 4) == 0)
- isEISA = TRUE;
-
- checked = TRUE;
+ if (strncmp((char *)0xfffd9, "EISA", 4) == 0)
+ isEISA = TRUE;
+
+ checked = TRUE;
}
return (isEISA);
ReadEISASlotInfo(EISA_slot_info_t *ep, int slot)
{
union {
- struct {
- unsigned char char2h :2;
- unsigned char char1 :5;
- unsigned char char3 :5;
- unsigned char char2l :3;
- unsigned char d2 :4;
- unsigned char d1 :4;
- unsigned char d4 :4;
- unsigned char d3 :4;
- } s;
- unsigned char data[4];
+ struct {
+ unsigned char char2h :2;
+ unsigned char char1 :5;
+ unsigned char char3 :5;
+ unsigned char char2l :3;
+ unsigned char d2 :4;
+ unsigned char d1 :4;
+ unsigned char d4 :4;
+ unsigned char d3 :4;
+ } s;
+ unsigned char data[4];
} u;
static char hex[0x10] = "0123456789ABCDEF";
-
+
bb.intno = 0x15;
bb.eax.r.h = 0xd8;
bb.ecx.r.l = slot;
bios(&bb);
if (bb.flags.cf)
- return bb.eax.r.h;
+ return bb.eax.r.h;
ep->u_ID.d = bb.eax.r.l;
ep->configMajor = bb.ebx.r.h;
ep->configMinor = bb.ebx.r.l;
bb.esi.rr = (unsigned int)ep->data;
bios(&bb);
if (bb.eax.r.h == 0) {
- ep->slot = slot;
- ep->function = function;
+ ep->slot = slot;
+ ep->function = function;
}
return bb.eax.r.h;
}
-#endif
+#endif /* EISA_SUPPORT */
#define PCI_SIGNATURE 0x20494350 /* "PCI " */
bb.eax.r.l = 0x01;
bios(&bb);
if ((bb.eax.r.h == 0) && (bb.edx.rx == PCI_SIGNATURE)) {
- pp->BIOSPresent = 1;
- pp->u_bus.d = bb.eax.r.l;
- pp->majorVersion = bb.ebx.r.h;
- pp->minorVersion = bb.ebx.r.l;
- pp->maxBusNum = bb.ecx.r.l;
- return 0;
+ pp->BIOSPresent = 1;
+ pp->u_bus.d = bb.eax.r.l;
+ pp->majorVersion = bb.ebx.r.h;
+ pp->minorVersion = bb.ebx.r.l;
+ pp->maxBusNum = bb.ecx.r.l;
+ return 0;
}
return -1;
}
* All rights reserved.
*/
-#include "io_inline.h"
#include "libsaio.h"
-#include "kernBootStruct.h"
// CMOS access ports in I/O space.
//
* Returns the number of active ATA drives since these will increment the
* bios device numbers of SCSI drives.
*/
-static int
-countIDEDisks()
+static int countIDEDisks()
{
int count = 0;
unsigned short hdtype;
KERNBOOTSTRUCT * kernBootStruct = (KERNBOOTSTRUCT *) KERNSTRUCT_ADDR;
-void
-initKernBootStruct()
+void initKernBootStruct( int biosdev )
{
+ static int init_done = 0;
unsigned char i;
- bzero( (char *) kernBootStruct, sizeof(*kernBootStruct) );
+ if ( !init_done )
+ {
+ bzero( (char *) kernBootStruct, sizeof(*kernBootStruct) );
- // Get size of conventional memory.
-
- kernBootStruct->convmem = memsize(0);
-
- // Get size of extended memory.
-
- kernBootStruct->extmem = memsize(1);
+ // Get size of conventional memory.
+
+ kernBootStruct->convmem = memsize(0);
+
+ // Get size of extended memory.
+
+ kernBootStruct->extmem = memsize(1);
+
+ kernBootStruct->magicCookie = KERNBOOTMAGIC;
+ kernBootStruct->configEnd = kernBootStruct->config;
+ kernBootStruct->graphicsMode = TEXT_MODE;
+
+ init_done = 1;
+ }
// Get number of ATA devices.
kernBootStruct->diskInfo[i] = get_diskinfo(0x80 + i);
}
- kernBootStruct->magicCookie = KERNBOOTMAGIC;
- kernBootStruct->configEnd = kernBootStruct->config;
- kernBootStruct->graphicsMode = GRAPHICS_MODE;
+ // Update kernDev from biosdev.
+
+ switch ( BIOS_DEV_TYPE( biosdev ) )
+ {
+ case kBIOSDevTypeNetwork:
+ kernBootStruct->kernDev = B_TYPE(DEV_EN); break;
+ case kBIOSDevTypeHardDrive:
+ kernBootStruct->kernDev = B_TYPE(DEV_HD); break;
+ case kBIOSDevTypeFloppy:
+ kernBootStruct->kernDev = B_TYPE(DEV_FD); break;
+ }
}
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
*
- * The Original Code and all software distributed under the License are
+ * This Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
-/* cache */
+/*
+ * cache.c - A simple cache for file systems meta-data.
+ *
+ * Copyright (c) 2000 Apple Computer, Inc.
+ *
+ * DRI: Josh de Cesare
+ */
-#include "cache.h"
-#include "libsa.h"
+#include <sl.h>
+// #include <fs.h>
-cache_t *cacheInit(
- int nitems,
- int item_size
-)
-{
- cache_t *cp;
- item_size += sizeof(item_t);
- cp = (cache_t *)malloc(sizeof(cache_t) + nitems * item_size);
- cp->nitems = nitems;
- cp->item_size = item_size;
- return cp;
-}
+struct CacheEntry {
+ CICell ih;
+ long time;
+ long long offset;
+};
+typedef struct CacheEntry CacheEntry;
-/*
- * Either find an item in the cache, or find where it should go.
- * Returns 1 if found, 0 if not found.
- * This function assumes that if you find an empty slot, you will use it;
- * therefore, empty slots returned are marked valid.
- */
-int cacheFind(
- cache_t *cp,
- int key1,
- int key2,
- char **ip
-)
+#define kCacheSize (0x100000)
+#define kCacheMinBlockSize (0x200)
+#define kCacheMaxBlockSize (0x4000)
+#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
+
+static CICell gCacheIH;
+static long gCacheBlockSize;
+static long gCacheNumEntries;
+static long gCacheTime;
+
+#ifdef __i386__
+static CacheEntry *gCacheEntries;
+static char *gCacheBuffer;
+#else
+static CacheEntry gCacheEntries[kCacheMaxEntries];
+static char gCacheBuffer[kCacheSize];
+#endif
+
+unsigned long gCacheHits;
+unsigned long gCacheMisses;
+unsigned long gCacheEvicts;
+
+void CacheInit( CICell ih, long blockSize )
{
- item_t *iip, *min_p;
- int i,j;
+#ifdef __i386__
+ if ((ih == gCacheIH) && (blockSize == gCacheBlockSize))
+ return;
+#endif
+
+ if ((blockSize < kCacheMinBlockSize) ||
+ (blockSize >= kCacheMaxBlockSize))
+ return;
+
+ gCacheBlockSize = blockSize;
+ gCacheNumEntries = kCacheSize / gCacheBlockSize;
+ gCacheTime = 0;
- for(i=j=0, iip = min_p = (item_t *)cp->storage; i < cp->nitems; i++) {
- if (iip->referenced && (iip->key1 == key1) && (iip->key2 == key2)) {
- *ip = iip->storage;
- if (iip->referenced < 65535)
- iip->referenced++;
- return 1;
- }
- if (iip->referenced < min_p->referenced) {
- min_p = iip;
- j = i;
- }
- iip = (item_t *)((char *)iip + cp->item_size);
+ gCacheHits = 0;
+ gCacheMisses = 0;
+ gCacheEvicts = 0;
+
+ gCacheIH = ih;
+
+#ifdef __i386__
+ if (!gCacheBuffer) gCacheBuffer = (char *) malloc(kCacheSize);
+ if (!gCacheEntries) gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry));
+ if ( !gCacheBuffer || !gCacheEntries )
+ {
+ gCacheIH = 0; // invalidate cache
+ return;
}
- *ip = min_p->storage;
- min_p->referenced = 1;
- min_p->key1 = key1;
- min_p->key2 = key2;
- return 0;
+#endif
+
+ bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry));
}
-/*
- * Flush the cache.
- */
-void cacheFlush(
- cache_t *cp
-)
+long CacheRead( CICell ih, char * buffer, long long offset,
+ long length, long cache )
{
- int i;
- item_t *ip;
-
- if (cp == 0)
- return;
- for(i=0, ip = (item_t *)cp->storage; i < cp->nitems; i++) {
- ip->referenced = 0;
- ip = (item_t *)((char *)ip + cp->item_size);
+ long cnt, oldestEntry = 0, oldestTime, loadCache = 0;
+ CacheEntry *entry;
+
+ // See if the data can be cached.
+ if (cache && (gCacheIH == ih) && (length == gCacheBlockSize)) {
+ // Look for the data in the cache.
+ for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
+ entry = &gCacheEntries[cnt];
+ if ((entry->ih == ih) && (entry->offset == offset)) {
+ entry->time = ++gCacheTime;
+ break;
+ }
+ }
+
+ // If the data was found copy it to the caller.
+ if (cnt != gCacheNumEntries) {
+ bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize);
+ gCacheHits++;
+ return gCacheBlockSize;
+ }
+
+ // Could not find the data in the cache.
+ loadCache = 1;
}
+
+ // Read the data from the disk.
+ Seek(ih, offset);
+ Read(ih, (long)buffer, length);
+ if (cache) gCacheMisses++;
+
+ // Put the data from the disk in the cache if needed.
+ if (loadCache) {
+ // Find a free entry.
+ oldestTime = gCacheTime;
+ for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
+ entry = &gCacheEntries[cnt];
+
+ // Found a free entry.
+ if (entry->ih == 0) break;
+
+ if (entry->time < oldestTime) {
+ oldestTime = entry->time;
+ oldestEntry = cnt;
+ }
+ }
+
+ // If no free entry was found, use the oldest.
+ if (cnt == gCacheNumEntries) {
+ cnt = oldestEntry;
+ gCacheEvicts++;
+ }
+
+ // Copy the data from disk to the new entry.
+ entry = &gCacheEntries[cnt];
+ entry->ih = ih;
+ entry->time = ++gCacheTime;
+ entry->offset = offset;
+ bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize);
+ }
+
+ return length;
}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __LIBSAIO_CACHE_H
-#define __LIBSAIO_CACHE_H
-
-typedef struct cache_item {
- unsigned int referenced;
- int key1, key2;
- char storage[0];
-} item_t;
-
-typedef struct cache {
- int nitems;
- int item_size;
- char storage[0];
-} cache_t;
-
-extern cache_t *cacheInit(
- int nitems,
- int item_size
-);
-
-extern int cacheFind(
- cache_t *cp,
- int key1,
- int key2,
- char **ip
-);
-
-extern void cacheFlush(
- cache_t *cp
-);
-
-#endif /* !__LIBSAIO_CACHE_H */
#include "libsaio.h"
BOOL gVerboseMode;
-BOOL errors;
+BOOL gErrors;
/*
* write one character to console
int error(const char * fmt, ...)
{
va_list ap;
- errors = YES;
+ gErrors = YES;
va_start(ap, fmt);
prf(fmt, ap, putchar, 0);
va_end(ap);
* All rights reserved.
*/
-#define DRIVER_PRIVATE
-
-#include "sys/types.h"
-#include "legacy/disk.h"
-#include "legacy/fdisk.h"
#include "libsaio.h"
-#include "memory.h"
-
-/*
- * Type and constant definitions.
- */
-typedef struct disk_blk0 boot_sector;
-#define BOOT_SIGNATURE DISK_SIGNATURE
-#define PART_TYPE_EXT 0x05
-#define PART_TYPE_APPLE 0xa8
-#define UFS_FRONT_PORCH 0
-
-#if DEBUG
-#define DPRINT(x) { printf x; }
-#define DSPRINT(x) { printf x; sleep(1); }
-#else
-#define DPRINT(x)
-#define DSPRINT(x)
-#endif
-
-/*
- * Function prototypes.
- */
-extern void spinActivityIndicator();
-static void diskActivityHook();
-static int Biosread(int biosdev, int secno);
-static struct fdisk_part * find_partition(u_int8_t type,
- u_int8_t biosdev,
- BOOL mba);
+#include "fdisk.h"
/*
* diskinfo unpacking.
*/
-#define SPT(di) ((di) & 0xff)
-#define HEADS(di) ((((di)>>8) & 0xff) + 1)
-#define SPC(di) (SPT(di) * HEADS(di))
-#define BPS 512 /* sector size of the device */
-#define N_CACHE_SECS (BIOS_LEN / BPS)
+#define SPT(di) ((di) & 0xff)
+#define HEADS(di) ((((di)>>8) & 0xff) + 1)
+#define SPC(di) (SPT(di) * HEADS(di))
-/*
- * Stores the geometry of the disk in order to
- * perform LBA to CHS translation for non EBIOS calls.
- */
-static struct diskinfo {
- int spt; /* sectors per track */
- int spc; /* sectors per cylinder */
-} diskinfo;
-
-/*
- * Globals variables.
- */
-int label_secsize = BPS;
-char * b[NBUFS];
-daddr_t blknos[NBUFS];
-struct iob iob[NFILES];
+#define BPS 512 /* sector size of the device */
+#define N_CACHE_SECS (BIOS_LEN / BPS)
+#define UFS_FRONT_PORCH 0
/*
- * intbuf points to the start of the sector cache. BIOS calls will
- * store the sectors read into this memory area. If cache_valid
- * is TRUE, then intbuf contents are valid. Otherwise, ignore the
- * cache and read from disk.
+ * trackbuf points to the start of the track cache. Biosread()
+ * will store the sectors read from disk to this memory area.
*
- * biosbuf points to a sector within the sector cache.
+ * biosbuf points to a sector within the track cache, and is
+ * updated by Biosread().
*/
-static char * const intbuf = (char *)ptov(BIOS_ADDR);
-static BOOL cache_valid = FALSE;
-static char * biosbuf;
+static const char * const trackbuf = (char *) ptov(BIOS_ADDR);
+static const char * biosbuf;
-/*==========================================================================
- *
+/*
+ * Map a disk drive to bootable volumes contained within.
*/
-void
-devopen(char * name, struct iob * io)
-{
- static int last_biosdev = -1;
- static daddr_t last_offset = 0;
+struct DiskBVMap {
+ int biosdev; // BIOS device number (unique)
+ BVRef bvr; // chain of boot volumes on the disk
+ int bvrcnt; // number of boot volumes
+ struct DiskBVMap * next; // linkage to next mapping
+};
- struct fdisk_part * part;
- long di;
+static struct DiskBVMap * gDiskBVMap = NULL;
+static struct disk_blk0 * gBootSector = NULL;
- io->i_error = 0;
- io->dirbuf_blkno = -1;
+extern long HFSInitPartition(CICell ih);
+extern long HFSLoadFile(CICell ih, char * filePath);
+extern long HFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time);
- // Use cached values if possible.
- //
- if (io->biosdev == last_biosdev) {
- io->i_boff = last_offset;
- return;
- }
+extern long UFSInitPartition(CICell ih);
+extern long UFSLoadFile(CICell ih, char * filePath);
+extern long UFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time);
- // initialize disk parameters -- spt and spc
- // must do this before doing reads from the device.
+extern void spinActivityIndicator();
- di = get_diskinfo(io->biosdev);
- if (di == 0) {
- io->i_error = ENXIO;
- return;
- }
+static void getVolumeDescription(BVRef bvr, char * str, long strMaxLen);
- diskinfo.spt = SPT(di);
- diskinfo.spc = diskinfo.spt * HEADS(di);
-
- // FIXME - io->partition is ignored. Doesn't make sense anymore.
- // we also don't overwrite the 'name' argument.
- // Whats special about "$LBL" ?
-
- part = find_partition(PART_TYPE_APPLE, io->biosdev, FALSE);
- if (part == NULL) {
- io->i_error = EIO;
- DSPRINT(("Unable to find partition: IO error\n"));
- } else {
- last_offset = io->i_boff = part->relsect + UFS_FRONT_PORCH/BPS;
- last_biosdev = io->biosdev;
- DSPRINT(("partition offset: %x\n", io->i_boff));
- }
-}
+//==========================================================================
-/*==========================================================================
- *
- */
-void devflush()
+static int getDiskGeometry( int biosdev, int * spt, int * spc )
{
- cache_valid = FALSE; // invalidate the sector cache (intbuf)
-}
-
-/*==========================================================================
- *
- */
-int devread(struct iob * io)
-{
- long sector;
- int offset;
-// int dev;
-
- io->i_flgs |= F_RDDATA;
+ static int cached_biosdev = -1;
+ static int cached_spt = 0;
+ static int cached_spc = 0;
+
+ if ( biosdev != cached_biosdev )
+ {
+ long di = get_diskinfo(biosdev);
+ if (di == 0) return (-1); // BIOS call error
- io->i_error = 0; // assume the best
+ cached_spt = SPT(di);
+ cached_spc = cached_spt * HEADS(di);
-// dev = io->i_ino.i_dev;
+ DEBUG_DISK(("%s: %d sectors, %d heads\n",
+ __FUNCTION__, cached_spt, (int)HEADS(di)));
+ }
- sector = io->i_bn * (label_secsize/BPS);
+ *spt = cached_spt;
+ *spc = cached_spc;
- for (offset = 0; offset < io->i_cc; offset += BPS) {
+ return 0;
+}
- io->i_error = Biosread(io->biosdev, sector);
- if (io->i_error)
- return (-1);
+//==========================================================================
+// Maps (E)BIOS return codes to message strings.
- /* copy 1 sector from the internal buffer biosbuf into buf */
- bcopy(biosbuf, &io->i_ma[offset], BPS);
+struct NamedValue {
+ unsigned char value;
+ const char * name;
+};
- sector++;
- }
+static const char * getNameForValue( const struct NamedValue * nameTable,
+ unsigned char value )
+{
+ const struct NamedValue * np;
- io->i_flgs &= ~F_TYPEMASK;
+ for ( np = nameTable; np->value; np++)
+ if (np->value == value)
+ return np->name;
- return (io->i_cc);
+ return NULL;
}
-/*==========================================================================
- * Maps (E)BIOS return codes to message strings.
- */
-struct bios_error_info {
- int errno;
- const char * string;
-};
-
#define ECC_CORRECTED_ERR 0x11
-static struct bios_error_info bios_errors[] = {
- {0x10, "Media error"},
- {0x11, "Corrected ECC error"},
- {0x20, "Controller or device error"},
- {0x40, "Seek failed"},
- {0x80, "Device timeout"},
- {0xAA, "Drive not ready"},
- {0x00, 0}
+static const struct NamedValue bios_errors[] = {
+ { 0x10, "Media error" },
+ { 0x11, "Corrected ECC error" },
+ { 0x20, "Controller or device error" },
+ { 0x40, "Seek failed" },
+ { 0x80, "Device timeout" },
+ { 0xAA, "Drive not ready" },
+ { 0x00, 0 }
};
-static const char *
-bios_error(int errno)
+static const char * bios_error(int errnum)
{
- struct bios_error_info * bp;
-
- for (bp = bios_errors; bp->errno; bp++) {
- if (bp->errno == errno)
- return bp->string;
- }
- return "Error 0x%02x"; // No string, print error code only
+ static char errorstr[] = "Error 0x00";
+ const char * errname;
+
+ errname = getNameForValue( bios_errors, errnum );
+ if ( errname ) return errname;
+
+ sprintf(errorstr, "Error 0x%02x", errnum);
+ return errorstr; // No string, print error code only
}
-/*==========================================================================
- * Use BIOS INT13 calls to read the sector specified. This function will
- * also perform read-ahead to cache a few subsequent sector to the sector
- * cache.
- *
- * The fields in diskinfo structure must be filled in before calling this
- * function.
- *
- * Return:
- * Return code from INT13/F2 or INT13/F42 call. If operation was
- * successful, 0 is returned.
- *
- */
-static int
-Biosread(int biosdev, int secno)
+//==========================================================================
+// Use BIOS INT13 calls to read the sector specified. This function will
+// also perform read-ahead to cache a few subsequent sector to the sector
+// cache.
+//
+// Return:
+// 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call.
+
+static int Biosread( int biosdev, unsigned int secno )
{
- static int xbiosdev, xcyl, xhead, xsec, xnsecs;
-
- extern unsigned char uses_ebios[];
+ static int xbiosdev, xcyl, xhead;
+ static unsigned int xsec, xnsecs;
+ static BOOL cache_valid = FALSE;
- int rc;
+ int rc = -1;
int cyl, head, sec;
int spt, spc;
int tries = 0;
- DSPRINT(("Biosread %d \n", secno));
+ // DEBUG_DISK(("Biosread dev %x sec %d \n", biosdev, secno));
// To read the disk sectors, use EBIOS if we can. Otherwise,
// revert to the standard BIOS calls.
- //
- if ((biosdev >= BIOS_DEV_HD) && uses_ebios[biosdev - BIOS_DEV_HD]) {
+
+ if ((biosdev >= kBIOSDevTypeHardDrive) &&
+ (uses_ebios[biosdev - kBIOSDevTypeHardDrive] & EBIOS_FIXED_DISK_ACCESS))
+ {
if (cache_valid &&
(biosdev == xbiosdev) &&
(secno >= xsec) &&
(secno < (xsec + xnsecs)))
{
- biosbuf = intbuf + (BPS * (secno - xsec));
+ biosbuf = trackbuf + (BPS * (secno - xsec));
return 0;
}
xnsecs = N_CACHE_SECS;
xsec = secno;
+ cache_valid = FALSE;
while ((rc = ebiosread(biosdev, secno, xnsecs)) && (++tries < 5))
{
if (rc == ECC_CORRECTED_ERR) {
/* Ignore corrected ECC errors */
+ rc = 0;
break;
}
error(" EBIOS read error: %s\n", bios_error(rc), rc);
sleep(1);
}
}
- else {
- spt = diskinfo.spt; // From previous INT13/F8 call.
- spc = diskinfo.spc;
-
+ else if ( getDiskGeometry(biosdev, &spt, &spc) == 0 )
+ {
cyl = secno / spc;
head = (secno % spc) / spt;
sec = secno % spt;
(sec >= xsec) &&
(sec < (xsec + xnsecs)))
{
- // this sector is in intbuf cache
- biosbuf = intbuf + (BPS * (sec - xsec));
+ // this sector is in trackbuf cache
+ biosbuf = trackbuf + (BPS * (sec - xsec));
return 0;
}
// Cache up to a track worth of sectors, but do not cross a
// track boundary.
- //
+
xcyl = cyl;
xhead = head;
xsec = sec;
xnsecs = ((sec + N_CACHE_SECS) > spt) ? (spt - sec) : N_CACHE_SECS;
+ cache_valid = FALSE;
while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) &&
(++tries < 5))
{
if (rc == ECC_CORRECTED_ERR) {
/* Ignore corrected ECC errors */
+ rc = 0;
break;
}
error(" BIOS read error: %s\n", bios_error(rc), rc);
}
// If the BIOS reported success, mark the sector cache as valid.
- //
+
if (rc == 0) {
cache_valid = TRUE;
}
- biosbuf = intbuf;
+ biosbuf = trackbuf;
xbiosdev = biosdev;
- diskActivityHook();
+ spinActivityIndicator();
return rc;
}
-/*==========================================================================
- * Replace this function if you want to change
- * the way disk activity is indicated to the user.
- */
-void
-diskActivityHook(void)
+//==========================================================================
+
+static int readBytes( int biosdev, unsigned int blkno,
+ unsigned int byteCount, void * buffer )
{
- spinActivityIndicator();
+
+ char * cbuf = (char *) buffer;
+ int error;
+ int copy_len;
+
+ DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__,
+ biosdev, blkno, byteCount, (unsigned)cbuf));
+
+ for ( ; byteCount; cbuf += BPS, blkno++ )
+ {
+ error = Biosread( biosdev, blkno );
+ if ( error )
+ {
+ DEBUG_DISK(("error\n"));
+ return (-1);
+ }
+
+ copy_len = (byteCount > BPS) ? BPS : byteCount;
+ bcopy( biosbuf, cbuf, copy_len );
+ byteCount -= copy_len;
+ }
+
+ DEBUG_DISK(("done\n"));
+
+ return 0;
}
-/*==========================================================================
- * Returns YES if the partition type specified is an extended fdisk
- * partition.
- */
-static BOOL
-isExtendedPartition(u_int8_t type)
+//==========================================================================
+
+static int isExtendedFDiskPartition( const struct fdisk_part * part )
{
- int i;
-
- u_int8_t extended_partitions[] = {
- 0x05, /* Extended */
- 0x0f, /* Win95 extended */
- 0x85, /* Linux extended */
- };
-
- for (i = 0;
- i < sizeof(extended_partitions)/sizeof(extended_partitions[0]);
- i++)
- {
- if (extended_partitions[i] == type)
- return YES;
- }
- return NO;
+ static unsigned char extParts[] =
+ {
+ 0x05, /* Extended */
+ 0x0f, /* Win95 extended */
+ 0x85, /* Linux extended */
+ };
+
+ int i;
+
+ for (i = 0; i < sizeof(extParts)/sizeof(extParts[0]); i++)
+ {
+ if (extParts[i] == part->systid) return 1;
+ }
+ return 0;
}
-/*==========================================================================
- * Traverse the fdisk partition tables on disk until a partition is found
- * that matches the specified type.
- *
- * Arguments:
- * type - Partition type to search for (e.g. 0xa7 for NeXTSTEP).
- * biosdev - BIOS device unit. 0x80 and up for hard-drive.
- * mba - If true, the partition found must be marked active.
- *
- * Return:
- * A pointer to the matching partition entry in biosbuf memory.
- * Note that the starting LBA field in the partition entry is
- * modified to contain the absolute sector address, rather than
- * the relative address.
- * A NULL is returned if a match is not found.
- *
- * There are certain fdisk rules that allows us to simplify the search.
- *
- * - There can be 0-1 extended partition entry in any partition table.
- * - In the MBR, there can be 0-4 primary partitions entries.
- * - In the extended partition, there can be 0-1 logical partition entry.
- *
- */
-struct fdisk_part *
-find_partition(u_int8_t type, u_int8_t biosdev, BOOL mba)
+//==========================================================================
+
+static int getNextFDiskPartition( int biosdev, int * partno,
+ const struct fdisk_part ** outPart )
{
-#define MAX_ITERATIONS 128
+ static int sBiosdev = -1;
+ static int sNextPartNo;
+ static unsigned int sExtBase;
+ static unsigned int sExtDepth;
+ static struct fdisk_part * sExtPart;
+ struct fdisk_part * part;
+
+ if ( sBiosdev != biosdev || *partno < 0 )
+ {
+ // Fetch MBR.
+ if ( readBootSector( biosdev, DISK_BLK0, 0 ) ) return 0;
+
+ sBiosdev = biosdev;
+ sNextPartNo = 0;
+ sExtBase = 0;
+ sExtDepth = 0;
+ sExtPart = NULL;
+ }
- static u_int32_t iter = 0;
- static u_int32_t offset_root;
- static u_int32_t offset;
+ while (1)
+ {
+ part = NULL;
- int n;
- int rc;
- boot_sector * bootsect;
- struct fdisk_part * match = 0;
- struct fdisk_part * parts;
+ if ( sNextPartNo < FDISK_NPART )
+ {
+ part = (struct fdisk_part *) gBootSector->parts[sNextPartNo];
+ }
+ else if ( sExtPart )
+ {
+ unsigned int blkno = sExtPart->relsect + sExtBase;
- if (iter == 0) {
- if (rc = Biosread(biosdev, 0)) // Read MBR at sector zero.
- return 0;
- offset = 0;
+ // Save the block offset of the first extended partition.
+
+ if ( sExtDepth == 0 ) sExtBase = sExtPart->relsect;
+
+ // Load extended partition table.
+
+ if ( readBootSector( biosdev, blkno, 0 ) == 0 )
+ {
+ sNextPartNo = 0;
+ sExtDepth++;
+ sExtPart = NULL;
+ continue;
+ }
+ }
+
+ if ( part == NULL ) break; // Reached end of partition chain.
+
+ // Advance to next partition number.
+
+ sNextPartNo++;
+
+ // Assume at most one extended partition per table.
+
+ if ( isExtendedFDiskPartition(part) )
+ {
+ sExtPart = part;
+ continue;
+ }
+
+ // Skip empty slots.
+
+ if ( part->systid == 0x00 )
+ {
+ continue;
+ }
+
+ // Change relative offset to an absolute offset.
+
+ part->relsect += sExtBase;
+
+ *outPart = part;
+ *partno = sExtDepth ? (sExtDepth + 4) : sNextPartNo;
+
+ break;
}
- bootsect = (boot_sector *) biosbuf;
- if (bootsect->signature != BOOT_SIGNATURE)
- return 0;
+ return (part != NULL);
+}
+
+//==========================================================================
- // Find a primary or a logical partition that matches the partition
- // type specified.
- //
- for (n = 0, parts = (struct fdisk_part *) bootsect->parts;
- n < 4;
- n++, parts++)
+static BVRef newFDiskBVRef( int biosdev, int partno, unsigned int blkoff,
+ const struct fdisk_part * part,
+ FSInit initFunc, FSLoadFile loadFunc,
+ FSGetDirEntry getdirFunc, int probe )
+{
+ BVRef bvr = (BVRef) malloc( sizeof(*bvr) );
+ if ( bvr )
{
- DSPRINT(("fdisk: [%d] %02x\n", iter, parts->systid));
+ bzero(bvr, sizeof(*bvr));
- if (mba && ((parts->bootid & 0x80) == 0))
- continue;
+ bvr->biosdev = biosdev;
+ bvr->part_no = partno;
+ bvr->part_boff = blkoff;
+ bvr->part_type = part->systid;
+ bvr->fs_loadfile = loadFunc;
+ bvr->fs_getdirentry = getdirFunc;
+ bvr->description = getVolumeDescription;
+
+ if ( part->bootid & FDISK_ACTIVE )
+ bvr->flags |= kBVFlagPrimary;
+
+ // Probe the filesystem.
+
+ if ( initFunc )
+ {
+ bvr->flags |= kBVFlagNativeBoot;
- if (parts->systid == type) {
- //
- // Found it!!!
- // Make the relsect field (LBA starting sector) absolute by
- // adding in the offset.
- //
- parts->relsect += offset;
+ if ( probe && initFunc( bvr ) != 0 )
+ {
+ // filesystem probe failed.
- DSPRINT(("Found: %x (%d)\n", parts->relsect, parts->numsect));
+ DEBUG_DISK(("%s: failed probe on dev %x part %d\n",
+ __FUNCTION__, biosdev, partno));
- return parts;
+ free(bvr);
+ bvr = NULL;
+ }
+ }
+ else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )
+ {
+ bvr->flags |= kBVFlagForeignBoot;
+ }
+ else
+ {
+ free(bvr);
+ bvr = NULL;
}
}
+ return bvr;
+}
- // Find if there is an extended partition entry that points to
- // an extended partition table. Note that we only allow up to
- // one extended partition per partition table.
- //
- for (n = 0, parts = (struct fdisk_part *) bootsect->parts;
- n < 4;
- n++, parts++)
- {
- DSPRINT(("fdisk: [E%d] %02x\n", iter, parts->systid));
+//==========================================================================
+
+BVRef diskScanBootVolumes( int biosdev, int * countPtr )
+{
+ const struct fdisk_part * part;
+ struct DiskBVMap * map;
+ int partno = -1;
+ BVRef bvr;
+ BVRef booterUFS = NULL;
+ int spc, spt;
- if (isExtendedPartition(parts->systid))
+ do {
+ // Find an existing mapping for this device.
+
+ for ( map = gDiskBVMap; map; map = map->next )
{
- if (iter > MAX_ITERATIONS) // limit recursion depth
- return 0;
+ if ( biosdev == map->biosdev ) break;
+ }
+ if ( map ) break;
- if (iter == 0)
- offset = offset_root = parts->relsect;
- else
- offset = parts->relsect + offset_root;
+ // Create a new mapping.
- iter++;
+ map = (struct DiskBVMap *) malloc( sizeof(*map) );
+ if ( map )
+ {
+ map->biosdev = biosdev;
+ map->bvr = NULL;
+ map->bvrcnt = 0;
+ map->next = gDiskBVMap;
+ gDiskBVMap = map;
- // Load extended partition table.
- //
- if (((rc = Biosread(biosdev, offset)) == 0) &&
- (bootsect->signature == BOOT_SIGNATURE))
+ // Create a record for each partition found on the disk.
+
+ while ( getNextFDiskPartition( biosdev, &partno, &part ) )
{
- match = find_partition(type, biosdev, mba);
+ DEBUG_DISK(("%s: part %d [%x]\n", __FUNCTION__,
+ partno, part->systid));
+
+ bvr = 0;
+
+ switch ( part->systid )
+ {
+ case FDISK_UFS:
+ bvr = newFDiskBVRef(
+ biosdev, partno,
+ part->relsect + UFS_FRONT_PORCH/BPS,
+ part,
+ UFSInitPartition,
+ UFSLoadFile,
+ UFSGetDirEntry,
+ 0 );
+ break;
+
+ case FDISK_HFS:
+ bvr = newFDiskBVRef(
+ biosdev, partno,
+ part->relsect,
+ part,
+ HFSInitPartition,
+ HFSLoadFile,
+ HFSGetDirEntry,
+ 0 );
+ break;
+
+ case FDISK_BOOTER:
+ if (getDiskGeometry(biosdev, &spt, &spc) != 0)
+ break;
+
+ booterUFS = newFDiskBVRef(
+ biosdev, partno,
+ ((part->relsect + spc - 1) / spc) * spc,
+ part,
+ UFSInitPartition,
+ UFSLoadFile,
+ UFSGetDirEntry,
+ 0 );
+ break;
+
+ default:
+ bvr = newFDiskBVRef(
+ biosdev, partno,
+ part->relsect,
+ part,
+ 0, 0, 0, 0 );
+ break;
+ }
+
+ if ( bvr )
+ {
+ bvr->next = map->bvr;
+ map->bvr = bvr;
+ map->bvrcnt++;
+ }
}
-
- iter--;
- break;
+ // Booting from a CD with an UFS filesystem embedded
+ // in a booter partition.
+
+ if ( booterUFS )
+ {
+ if ( map->bvrcnt == 0 )
+ {
+ map->bvr = booterUFS;
+ map->bvrcnt++;
+ }
+ else free( booterUFS );
+ }
+ }
+ } while (0);
+
+ if (countPtr) *countPtr = map ? map->bvrcnt : 0;
+
+ return map ? map->bvr : NULL;
+}
+
+//==========================================================================
+
+static const struct NamedValue fdiskTypes[] =
+{
+ { 0x07, "Windows NTFS" },
+ { 0x0c, "Windows FAT32" },
+ { 0x83, "Linux" },
+ { FDISK_UFS, "Apple UFS" },
+ { FDISK_HFS, "Apple HFS" },
+ { FDISK_BOOTER, "Apple Boot/UFS" },
+ { 0x00, 0 } /* must be last */
+};
+
+static void getVolumeDescription( BVRef bvr, char * str, long strMaxLen )
+{
+ unsigned char type = (unsigned char) bvr->part_type;
+ const char * name = getNameForValue( fdiskTypes, type );
+
+ if ( name )
+ sprintf( str, "hd(%d,%d) %s",
+ BIOS_DEV_UNIT(bvr->biosdev), bvr->part_no, name );
+ else
+ sprintf( str, "hd(%d,%d) TYPE %02x",
+ BIOS_DEV_UNIT(bvr->biosdev), bvr->part_no, type );
+}
+
+//==========================================================================
+
+int readBootSector( int biosdev, unsigned int secno, void * buffer )
+{
+ struct disk_blk0 * bootSector = (struct disk_blk0 *) buffer;
+ int error;
+
+ if ( bootSector == NULL )
+ {
+ if ( gBootSector == NULL )
+ {
+ gBootSector = (struct disk_blk0 *) malloc(sizeof(*gBootSector));
+ if ( gBootSector == NULL ) return -1;
}
+ bootSector = gBootSector;
}
-
- return match;
+
+ error = readBytes( biosdev, secno, BPS, bootSector );
+ if ( error || bootSector->signature != DISK_SIGNATURE )
+ return -1;
+
+ return 0;
+}
+
+//==========================================================================
+// Handle seek request from filesystem modules.
+
+void diskSeek( BVRef bvr, long long position )
+{
+ bvr->fs_boff = position / BPS;
+}
+
+//==========================================================================
+// Handle read request from filesystem modules.
+
+int diskRead( BVRef bvr, long addr, long length )
+{
+ return readBytes( bvr->biosdev,
+ bvr->fs_boff + bvr->part_boff,
+ length,
+ (void *) addr );
}
--- /dev/null
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License"). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992 NeXT Computer, Inc.
+ *
+ * IBM PC disk partitioning data structures.
+ *
+ * HISTORY
+ *
+ * 8 July 1992 David E. Bohman at NeXT
+ * Created.
+ */
+
+#ifndef __LIBSAIO_FDISK_H
+#define __LIBSAIO_FDISK_H
+
+#define DISK_BLK0 0 /* blkno of boot block */
+#define DISK_BLK0SZ 512 /* size of boot block */
+#define DISK_BOOTSZ 446 /* size of boot code in boot block */
+#define DISK_SIGNATURE 0xAA55 /* signature of the boot record */
+#define FDISK_NPART 4 /* number of entries in fdisk table */
+#define FDISK_ACTIVE 0x80 /* indicator of active partition */
+#define FDISK_NEXTNAME 0xA7 /* indicator of NeXT partition */
+#define FDISK_DOS12 0x01 /* 12-bit fat < 10MB dos partition */
+#define FDISK_DOS16S 0x04 /* 16-bit fat < 32MB dos partition */
+#define FDISK_DOSEXT 0x05 /* extended dos partition */
+#define FDISK_DOS16B 0x06 /* 16-bit fat >= 32MB dos partition */
+#define FDISK_UFS 0xa8 /* Apple UFS partition */
+#define FDISK_HFS 0xaf /* Apple HFS partition */
+#define FDISK_BOOTER 0xab /* Apple booter partition */
+
+/*
+ * Format of fdisk partion entry (if present).
+ */
+struct fdisk_part {
+ unsigned char bootid; /* bootable or not */
+ unsigned char beghead; /* begining head, sector, cylinder */
+ unsigned char begsect; /* begcyl is a 10-bit number */
+ unsigned char begcyl; /* High 2 bits are in begsect */
+ unsigned char systid; /* OS type */
+ unsigned char endhead; /* ending head, sector, cylinder */
+ unsigned char endsect; /* endcyl is a 10-bit number */
+ unsigned char endcyl; /* High 2 bits are in endsect */
+ unsigned long relsect; /* partion physical offset on disk */
+ unsigned long numsect; /* number of sectors in partition */
+};
+
+/*
+ * Format of boot block.
+ */
+struct disk_blk0 {
+ unsigned char bootcode[DISK_BOOTSZ];
+ unsigned char parts[FDISK_NPART][sizeof (struct fdisk_part)];
+ unsigned short signature;
+};
+
+#endif /* !__LIBSAIO_FDISK_H */
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1993, NeXT Computer Inc.
- * All rights reserved.
- */
-
-#include "libsaio.h"
-
-int gets( char * buf, int len )
-{
- char *lp = buf, *end = buf + len - 1;
- int c;
-
- flushdev(); // XXX
-
- for (;;) {
- c = getchar() & 0x7f;
- if (c < ' ' && c != '\n' && c != '\b') c = 0;
- if (c == 0x7f) c = '\b';
-
- switch(c)
- {
- case '\0':
- continue;
- case '\n':
- *lp++ = '\0';
- putchar('\n');
- return 1;
- case '\b':
- if (lp > buf) {
- lp--;
- putchar('\b');
- putchar(' ');
- putchar('\b');
- }
- continue;
- default:
- if (lp < end)
- *lp++ = c;
- else
- {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- putchar('\007');
- }
- }
- }
-}
-
-/*
- * Return a string in buf if typing has begun within timeout units.
- */
-int
-Gets( char * buf,
- int len,
- int timeout,
- char * prompt,
- char * message )
-{
- int ch = 0;
- int next_second;
-
- flushdev(); // XXX
-
- printf("%s", prompt);
-
- if (message)
- printf("%s", message);
-
- if (timeout)
- {
- for ( next_second = time18() + 18; timeout; )
- {
- if (ch = readKeyboardStatus())
- {
- break;
- }
- if ( time18() >= next_second )
- {
- next_second += 18;
- timeout--;
- }
- }
-
- if (ch == 0)
- {
- printf("\n");
- return 0;
- }
- }
- return ( gets(buf, len) );
-}
--- /dev/null
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * hfs.c - File System Module for HFS and HFS+.
+ *
+ * Copyright (c) 1999-2002 Apple Computer, Inc.
+ *
+ * DRI: Josh de Cesare
+ */
+
+#include <sl.h>
+#include <hfs/hfs_format.h>
+
+#define kBlockSize (0x200)
+
+#define kMDBBaseOffset (2 * kBlockSize)
+
+#define kBTreeCatalog (0)
+#define kBTreeExtents (1)
+
+#ifdef __i386__
+
+static CICell gCurrentIH;
+static long long gAllocationOffset;
+static long gIsHFSPlus;
+static long gBlockSize;
+static long gCacheBlockSize;
+static char *gBTreeHeaderBuffer;
+static BTHeaderRec *gBTHeaders[2];
+static char *gHFSMdbVib;
+static HFSMasterDirectoryBlock *gHFSMDB;
+static char *gHFSPlusHeader;
+static HFSPlusVolumeHeader *gHFSPlus;
+static char *gLinkTemp;
+static char *gTempStr;
+
+#else /* !__i386__ */
+
+static CICell gCurrentIH;
+static long long gAllocationOffset;
+static long gIsHFSPlus;
+static long gBlockSize;
+static long gCacheBlockSize;
+static char gBTreeHeaderBuffer[512];
+static BTHeaderRec *gBTHeaders[2];
+static char gHFSMdbVib[kBlockSize];
+static HFSMasterDirectoryBlock *gHFSMDB =(HFSMasterDirectoryBlock*)gHFSMdbVib;
+static char gHFSPlusHeader[kBlockSize];
+static HFSPlusVolumeHeader *gHFSPlus =(HFSPlusVolumeHeader*)gHFSPlusHeader;
+static char gLinkTemp[64];
+
+#endif /* !__i386__ */
+
+static long ReadFile(void *file, long *length);
+static long GetCatalogEntryInfo(void *entry, long *flags, long *time);
+static long ResolvePathToCatalogEntry(char *filePath, long *flags,
+ void *entry, long dirID, long *dirIndex);
+
+static long GetCatalogEntry(long *dirIndex, char **name,
+ long *flags, long *time);
+static long ReadCatalogEntry(char *fileName, long dirID, void *entry,
+ long *dirIndex);
+static long ReadExtentsEntry(long fileID, long startBlock, void *entry);
+
+static long ReadBTreeEntry(long btree, void *key, char *entry, long *dirIndex);
+static void GetBTreeRecord(long index, char *nodeBuffer, long nodeSize,
+ char **key, char **data);
+
+static long ReadExtent(char *extent, long extentSize, long extentFile,
+ long offset, long size, void *buffer, long cache);
+
+static long GetExtentStart(void *extents, long index);
+static long GetExtentSize(void *extents, long index);
+
+static long CompareHFSCatalogKeys(void *key, void *testKey);
+static long CompareHFSPlusCatalogKeys(void *key, void *testKey);
+static long CompareHFSExtentsKeys(void *key, void *testKey);
+static long CompareHFSPlusExtentsKeys(void *key, void *testKey);
+
+extern long FastRelString(char *str1, char *str2);
+extern long FastUnicodeCompare(u_int16_t *uniStr1, u_int32_t len1,
+ u_int16_t *uniStr2, u_int32_t len2);
+extern void utf_encodestr(const u_int16_t *ucsp, int ucslen,
+ u_int8_t *utf8p, u_int32_t bufsize);
+extern void utf_decodestr(const u_int8_t *utf8p, u_int16_t *ucsp,
+ u_int16_t *ucslen, u_int32_t bufsize);
+
+
+long HFSInitPartition(CICell ih)
+{
+ long extentSize, extentFile, nodeSize;
+ void *extent;
+
+ if (ih == gCurrentIH) {
+#ifdef __i386__
+ CacheInit(ih, gCacheBlockSize);
+#endif
+ return 0;
+ }
+
+ verbose("HFSInitPartition: %x\n", ih);
+
+#ifdef __i386__
+ if (!gTempStr) gTempStr = (char *)malloc(4096);
+ if (!gLinkTemp) gLinkTemp = (char *)malloc(64);
+ if (!gBTreeHeaderBuffer) gBTreeHeaderBuffer = (char *)malloc(512);
+ if (!gHFSMdbVib) {
+ gHFSMdbVib = (char *)malloc(kBlockSize);
+ gHFSMDB = (HFSMasterDirectoryBlock *)gHFSMdbVib;
+ }
+ if (!gHFSPlusHeader) {
+ gHFSPlusHeader = (char *)malloc(kBlockSize);
+ gHFSPlus = (HFSPlusVolumeHeader *)gHFSPlusHeader;
+ }
+ if (!gTempStr || !gLinkTemp || !gBTreeHeaderBuffer ||
+ !gHFSMdbVib || !gHFSPlusHeader) return -1;
+#endif /* __i386__ */
+
+ gAllocationOffset = 0;
+ gIsHFSPlus = 0;
+ gBTHeaders[0] = 0;
+ gBTHeaders[1] = 0;
+
+ // Look for the HFS MDB
+ Seek(ih, kMDBBaseOffset);
+ Read(ih, (long)gHFSMdbVib, kBlockSize);
+
+ if ( SWAP_BE16(gHFSMDB->drSigWord) == kHFSSigWord ) {
+ gAllocationOffset = SWAP_BE16(gHFSMDB->drAlBlSt) * kBlockSize;
+
+ // See if it is HFSPlus
+ if (SWAP_BE16(gHFSMDB->drEmbedSigWord) != kHFSPlusSigWord) {
+ // Normal HFS;
+ gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSMDB->drAlBlkSiz);
+ CacheInit(ih, gCacheBlockSize);
+ gCurrentIH = ih;
+
+ // Get the Catalog BTree node size.
+ extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
+ extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
+ extentFile = kHFSCatalogFileID;
+ ReadExtent(extent, extentSize, extentFile, 0, 256,
+ gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);
+
+ nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 +
+ sizeof(BTNodeDescriptor)))->nodeSize);
+
+ // If the BTree node size is larger than the block size, reset the cache.
+ if (nodeSize > gBlockSize) {
+ gCacheBlockSize = nodeSize;
+ CacheInit(ih, gCacheBlockSize);
+ }
+
+ return 0;
+ }
+
+ // Calculate the offset to the embeded HFSPlus volume.
+ gAllocationOffset += (long long)SWAP_BE16(gHFSMDB->drEmbedExtent.startBlock) *
+ SWAP_BE32(gHFSMDB->drAlBlkSiz);
+ }
+
+ // Look for the HFSPlus Header
+ Seek(ih, gAllocationOffset + kMDBBaseOffset);
+ Read(ih, (long)gHFSPlusHeader, kBlockSize);
+
+ // Not a HFS[+] volume.
+ if (SWAP_BE16(gHFSPlus->signature) != kHFSPlusSigWord) return -1;
+
+ gIsHFSPlus = 1;
+ gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSPlus->blockSize);
+ CacheInit(ih, gCacheBlockSize);
+ gCurrentIH = ih;
+
+ // Get the Catalog BTree node size.
+ extent = &gHFSPlus->catalogFile.extents;
+ extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
+ extentFile = kHFSCatalogFileID;
+
+ ReadExtent(extent, extentSize, extentFile, 0, 256,
+ gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);
+
+ nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 +
+ sizeof(BTNodeDescriptor)))->nodeSize);
+
+ // If the BTree node size is larger than the block size, reset the cache.
+ if (nodeSize > gBlockSize) {
+ gCacheBlockSize = nodeSize;
+ CacheInit(ih, gCacheBlockSize);
+ }
+
+ return 0;
+}
+
+long HFSLoadFile(CICell ih, char * filePath)
+{
+ char entry[512];
+ long dirID, result, length, flags;
+
+ if (HFSInitPartition(ih) == -1) return -1;
+
+ verbose("Loading HFS%s file: [%s] from %x.\n",
+ (gIsHFSPlus ? "+" : ""), filePath, ih);
+
+ dirID = kHFSRootFolderID;
+ // Skip a lead '\'. Start in the system folder if there are two.
+ if (filePath[0] == '/') {
+ if (filePath[1] == '/') {
+ if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
+ else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
+ if (dirID == 0) return -1;
+ filePath++;
+ }
+ filePath++;
+ }
+
+ result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0);
+ if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) return -1;
+
+#if 0 // Not yet for Intel. System.config/Default.table will fail this check.
+ // Check file owner and permissions.
+ if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1;
+#endif
+
+ result = ReadFile(entry, &length);
+ if (result == -1) return -1;
+
+ return length;
+}
+
+long HFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex, char ** name,
+ long * flags, long * time)
+{
+ char entry[512];
+ long dirID, dirFlags;
+
+ if (HFSInitPartition(ih) == -1) return -1;
+
+ if (*dirIndex == -1) return -1;
+
+ dirID = kHFSRootFolderID;
+ // Skip a lead '\'. Start in the system folder if there are two.
+ if (dirPath[0] == '/') {
+ if (dirPath[1] == '/') {
+ if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
+ else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
+ if (dirID == 0) return -1;
+ dirPath++;
+ }
+ dirPath++;
+ }
+
+ if (*dirIndex == 0) {
+ ResolvePathToCatalogEntry(dirPath, &dirFlags, entry, dirID, dirIndex);
+ if (*dirIndex == 0) *dirIndex = -1;
+ if ((dirFlags & kFileTypeMask) != kFileTypeUnknown) return -1;
+ }
+
+ GetCatalogEntry(dirIndex, name, flags, time);
+ if (*dirIndex == 0) *dirIndex = -1;
+ if ((*flags & kFileTypeMask) == kFileTypeUnknown) return -1;
+
+ return 0;
+}
+
+// Private Functions
+
+static long ReadFile(void * file, long * length)
+{
+ void *extents;
+ long fileID;
+ HFSCatalogFile *hfsFile = file;
+ HFSPlusCatalogFile *hfsPlusFile = file;
+
+ if (gIsHFSPlus) {
+ fileID = SWAP_BE32(hfsPlusFile->fileID);
+ *length = SWAP_BE64(hfsPlusFile->dataFork.logicalSize);
+ extents = &hfsPlusFile->dataFork.extents;
+ } else {
+ fileID = SWAP_BE32(hfsFile->fileID);
+ *length = SWAP_BE32(hfsFile->dataLogicalSize);
+ extents = &hfsFile->dataExtents;
+ }
+
+ if (*length > kLoadSize) {
+ printf("File is too large.\n");
+ return -1;
+ }
+
+#ifdef __i386__
+ *length = ReadExtent((char *)extents, *length, fileID,
+ 0, *length, (char *)gFSLoadAddress, 0);
+#else
+ *length = ReadExtent((char *)extents, *length, fileID,
+ 0, *length, (char *)kLoadAddr, 0);
+#endif
+
+ return 0;
+}
+
+static long GetCatalogEntryInfo(void * entry, long * flags, long * time)
+{
+ long tmpTime = 0;
+
+ // Get information about the file.
+
+ switch ( SWAP_BE16(*(short *)entry) )
+ {
+ case kHFSFolderRecord :
+ *flags = kFileTypeDirectory;
+ tmpTime = SWAP_BE32(((HFSCatalogFolder *)entry)->modifyDate);
+ break;
+
+ case kHFSPlusFolderRecord :
+ *flags = kFileTypeDirectory |
+ (SWAP_BE16(((HFSPlusCatalogFolder *)entry)->bsdInfo.fileMode) & kPermMask);
+ if (SWAP_BE32(((HFSPlusCatalogFolder *)entry)->bsdInfo.ownerID) != 0)
+ *flags |= kOwnerNotRoot;
+ tmpTime = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->contentModDate);
+ break;
+
+ case kHFSFileRecord :
+ *flags = kFileTypeFlat;
+ tmpTime = SWAP_BE32(((HFSCatalogFile *)entry)->modifyDate);
+ break;
+
+ case kHFSPlusFileRecord :
+ *flags = kFileTypeFlat |
+ (SWAP_BE16(((HFSPlusCatalogFile *)entry)->bsdInfo.fileMode) & kPermMask);
+ if (SWAP_BE32(((HFSPlusCatalogFile *)entry)->bsdInfo.ownerID) != 0)
+ *flags |= kOwnerNotRoot;
+ tmpTime = SWAP_BE32(((HFSPlusCatalogFile *)entry)->contentModDate);
+ break;
+
+ case kHFSFileThreadRecord :
+ case kHFSPlusFileThreadRecord :
+ case kHFSFolderThreadRecord :
+ case kHFSPlusFolderThreadRecord :
+ *flags = kFileTypeUnknown;
+ tmpTime = 0;
+ break;
+ }
+
+ if (time != 0) {
+ // Convert base time from 1904 to 1970.
+ *time = tmpTime - 2082844800;
+ }
+
+ return 0;
+}
+
+static long ResolvePathToCatalogEntry(char * filePath, long * flags,
+ void * entry, long dirID, long * dirIndex)
+{
+ char *restPath;
+ long result, cnt, subFolderID, tmpDirIndex;
+ HFSPlusCatalogFile *hfsPlusFile;
+
+ // Copy the file name to gTempStr
+ cnt = 0;
+ while ((filePath[cnt] != '/') && (filePath[cnt] != '\0')) cnt++;
+ strncpy(gTempStr, filePath, cnt);
+
+ // Move restPath to the right place.
+ if (filePath[cnt] != '\0') cnt++;
+ restPath = filePath + cnt;
+
+ // gTempStr is a name in the current Dir.
+ // restPath is the rest of the path if any.
+
+ result = ReadCatalogEntry(gTempStr, dirID, entry, dirIndex);
+ if (result == -1) return -1;
+
+ GetCatalogEntryInfo(entry, flags, 0);
+
+ if ((*flags & kFileTypeMask) == kFileTypeDirectory) {
+ if (gIsHFSPlus)
+ subFolderID = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->folderID);
+ else
+ subFolderID = SWAP_BE32(((HFSCatalogFolder *)entry)->folderID);
+
+ result = ResolvePathToCatalogEntry(restPath, flags, entry,
+ subFolderID, dirIndex);
+ }
+
+ if (gIsHFSPlus && ((*flags & kFileTypeMask) == kFileTypeFlat)) {
+ hfsPlusFile = (HFSPlusCatalogFile *)entry;
+ if ((SWAP_BE32(hfsPlusFile->userInfo.fdType) == kHardLinkFileType) &&
+ (SWAP_BE32(hfsPlusFile->userInfo.fdCreator) == kHFSPlusCreator)) {
+ sprintf(gLinkTemp, "%s/%s%ld", HFSPLUSMETADATAFOLDER,
+ HFS_INODE_PREFIX, SWAP_BE32(hfsPlusFile->bsdInfo.special.iNodeNum));
+ result = ResolvePathToCatalogEntry(gLinkTemp, flags, entry,
+ kHFSRootFolderID, &tmpDirIndex);
+ }
+ }
+
+ return result;
+}
+
+static long GetCatalogEntry(long * dirIndex, char ** name,
+ long * flags, long * time)
+{
+ long extentSize, nodeSize, curNode, index;
+ void *extent;
+ char *nodeBuf, *testKey, *entry;
+ BTNodeDescriptor *node;
+
+ if (gIsHFSPlus) {
+ extent = &gHFSPlus->catalogFile.extents;
+ extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
+ } else {
+ extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
+ extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
+ }
+
+ nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize);
+ nodeBuf = (char *)malloc(nodeSize);
+ node = (BTNodeDescriptor *)nodeBuf;
+
+ index = *dirIndex % nodeSize;
+ curNode = *dirIndex / nodeSize;
+
+ // Read the BTree node and get the record for index.
+ ReadExtent(extent, extentSize, kHFSCatalogFileID,
+ curNode * nodeSize, nodeSize, nodeBuf, 1);
+ GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry);
+
+ GetCatalogEntryInfo(entry, flags, time);
+
+ // Get the file name.
+ if (gIsHFSPlus) {
+ utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode,
+ SWAP_BE16(((HFSPlusCatalogKey *)testKey)->nodeName.length),
+ gTempStr, 256);
+ } else {
+ strncpy(gTempStr,
+ &((HFSCatalogKey *)testKey)->nodeName[1],
+ ((HFSCatalogKey *)testKey)->nodeName[0]);
+ }
+ *name = gTempStr;
+
+ // Update dirIndex.
+ index++;
+ if (index == SWAP_BE16(node->numRecords)) {
+ index = 0;
+ curNode = SWAP_BE32(node->fLink);
+ }
+ *dirIndex = curNode * nodeSize + index;
+
+ free(nodeBuf);
+
+ return 0;
+}
+
+static long ReadCatalogEntry(char * fileName, long dirID,
+ void * entry, long * dirIndex)
+{
+ long length;
+ char key[sizeof(HFSPlusCatalogKey)];
+ HFSCatalogKey *hfsKey = (HFSCatalogKey *)key;
+ HFSPlusCatalogKey *hfsPlusKey = (HFSPlusCatalogKey *)key;
+
+ // Make the catalog key.
+ if ( gIsHFSPlus )
+ {
+ hfsPlusKey->parentID = SWAP_BE32(dirID);
+ length = strlen(fileName);
+ if (length > 255) length = 255;
+ utf_decodestr(fileName, hfsPlusKey->nodeName.unicode,
+ &(hfsPlusKey->nodeName.length), 512);
+ } else {
+ hfsKey->parentID = SWAP_BE32(dirID);
+ length = strlen(fileName);
+ if (length > 31) length = 31;
+ hfsKey->nodeName[0] = length;
+ strncpy(hfsKey->nodeName + 1, fileName, length);
+ }
+
+ return ReadBTreeEntry(kBTreeCatalog, &key, entry, dirIndex);
+}
+
+static long ReadExtentsEntry(long fileID, long startBlock, void * entry)
+{
+ char key[sizeof(HFSPlusExtentKey)];
+ HFSExtentKey *hfsKey = (HFSExtentKey *)key;
+ HFSPlusExtentKey *hfsPlusKey = (HFSPlusExtentKey *)key;
+
+ // Make the extents key.
+ if (gIsHFSPlus) {
+ hfsPlusKey->forkType = 0;
+ hfsPlusKey->fileID = SWAP_BE32(fileID);
+ hfsPlusKey->startBlock = SWAP_BE32(startBlock);
+ } else {
+ hfsKey->forkType = 0;
+ hfsKey->fileID = SWAP_BE32(fileID);
+ hfsKey->startBlock = SWAP_BE16(startBlock);
+ }
+
+ return ReadBTreeEntry(kBTreeExtents, &key, entry, 0);
+}
+
+static long ReadBTreeEntry(long btree, void * key, char * entry, long * dirIndex)
+{
+ long extentSize;
+ void *extent;
+ short extentFile;
+ char *nodeBuf;
+ BTNodeDescriptor *node;
+ long nodeSize, result = 0, entrySize = 0;
+ long curNode, index = 0, lowerBound, upperBound;
+ char *testKey, *recordData;
+
+ // Figure out which tree is being looked at.
+ if (btree == kBTreeCatalog) {
+ if (gIsHFSPlus) {
+ extent = &gHFSPlus->catalogFile.extents;
+ extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
+ } else {
+ extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
+ extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
+ }
+ extentFile = kHFSCatalogFileID;
+ } else {
+ if (gIsHFSPlus) {
+ extent = &gHFSPlus->extentsFile.extents;
+ extentSize = SWAP_BE64(gHFSPlus->extentsFile.logicalSize);
+ } else {
+ extent = (HFSExtentDescriptor *)&gHFSMDB->drXTExtRec;
+ extentSize = SWAP_BE32(gHFSMDB->drXTFlSize);
+ }
+ extentFile = kHFSExtentsFileID;
+ }
+
+ // Read the BTree Header if needed.
+ if (gBTHeaders[btree] == 0) {
+ ReadExtent(extent, extentSize, extentFile, 0, 256,
+ gBTreeHeaderBuffer + btree * 256, 0);
+ gBTHeaders[btree] = (BTHeaderRec *)(gBTreeHeaderBuffer + btree * 256 +
+ sizeof(BTNodeDescriptor));
+ }
+
+ curNode = SWAP_BE32(gBTHeaders[btree]->rootNode);
+ nodeSize = SWAP_BE16(gBTHeaders[btree]->nodeSize);
+ nodeBuf = (char *)malloc(nodeSize);
+ node = (BTNodeDescriptor *)nodeBuf;
+
+ while (1) {
+ // Read the current node.
+ ReadExtent(extent, extentSize, extentFile,
+ curNode * nodeSize, nodeSize, nodeBuf, 1);
+
+ // Find the matching key.
+ lowerBound = 0;
+ upperBound = SWAP_BE16(node->numRecords) - 1;
+ while (lowerBound <= upperBound) {
+ index = (lowerBound + upperBound) / 2;
+
+ GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData);
+
+ if (gIsHFSPlus) {
+ if (btree == kBTreeCatalog) {
+ result = CompareHFSPlusCatalogKeys(key, testKey);
+ } else {
+ result = CompareHFSPlusExtentsKeys(key, testKey);
+ }
+ } else {
+ if (btree == kBTreeCatalog) {
+ result = CompareHFSCatalogKeys(key, testKey);
+ } else {
+ result = CompareHFSExtentsKeys(key, testKey);
+ }
+ }
+
+ if (result < 0) upperBound = index - 1; // search < trial
+ else if (result > 0) lowerBound = index + 1; // search > trial
+ else break; // search = trial
+ }
+
+ if (result < 0) {
+ index = upperBound;
+ GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData);
+ }
+
+ // Found the closest key... Recurse on it if this is an index node.
+ if (node->kind == kBTIndexNode) {
+ curNode = SWAP_BE32( *((long *)recordData) );
+ } else break;
+ }
+
+ // Return error if the file was not found.
+ if (result != 0) { free(nodeBuf); return -1; }
+
+ if (btree == kBTreeCatalog) {
+ switch (SWAP_BE16(*(short *)recordData)) {
+ case kHFSFolderRecord : entrySize = 70; break;
+ case kHFSFileRecord : entrySize = 102; break;
+ case kHFSFolderThreadRecord : entrySize = 46; break;
+ case kHFSFileThreadRecord : entrySize = 46; break;
+ case kHFSPlusFolderRecord : entrySize = 88; break;
+ case kHFSPlusFileRecord : entrySize = 248; break;
+ case kHFSPlusFolderThreadRecord : entrySize = 264; break;
+ case kHFSPlusFileThreadRecord : entrySize = 264; break;
+ }
+ } else {
+ if (gIsHFSPlus) entrySize = sizeof(HFSPlusExtentRecord);
+ else entrySize = sizeof(HFSExtentRecord);
+ }
+
+ bcopy(recordData, entry, entrySize);
+
+ // Update dirIndex.
+ if (dirIndex != 0) {
+ index++;
+ if (index == SWAP_BE16(node->numRecords)) {
+ index = 0;
+ curNode = SWAP_BE32(node->fLink);
+ }
+ *dirIndex = curNode * nodeSize + index;
+ }
+
+ free(nodeBuf);
+
+ return 0;
+}
+
+static void GetBTreeRecord(long index, char * nodeBuffer, long nodeSize,
+ char ** key, char ** data)
+{
+ long keySize;
+ long recordOffset;
+
+ recordOffset = SWAP_BE16(*((short *)(nodeBuffer + (nodeSize - 2 * index - 2))));
+ *key = nodeBuffer + recordOffset;
+ if (gIsHFSPlus) {
+ keySize = SWAP_BE16(*(short *)*key);
+ *data = *key + 2 + keySize;
+ } else {
+ keySize = **key;
+ *data = *key + 2 + keySize - (keySize & 1);
+ }
+}
+
+static long ReadExtent(char * extent, long extentSize,
+ long extentFile, long offset, long size,
+ void * buffer, long cache)
+{
+ long lastOffset, blockNumber, countedBlocks = 0;
+ long nextExtent = 0, sizeRead = 0, readSize;
+ long nextExtentBlock, currentExtentBlock = 0;
+ long long readOffset;
+ long extentDensity, sizeofExtent, currentExtentSize;
+ char *currentExtent, *extentBuffer = 0, *bufferPos = buffer;
+
+ if (offset >= extentSize) return 0;
+
+ if (gIsHFSPlus) {
+ extentDensity = kHFSPlusExtentDensity;
+ sizeofExtent = sizeof(HFSPlusExtentDescriptor);
+ } else {
+ extentDensity = kHFSExtentDensity;
+ sizeofExtent = sizeof(HFSExtentDescriptor);
+ }
+
+ lastOffset = offset + size;
+ while (offset < lastOffset) {
+ blockNumber = offset / gBlockSize;
+
+ // Find the extent for the offset.
+ for (; ; nextExtent++) {
+ if (nextExtent < extentDensity) {
+ if ((countedBlocks+GetExtentSize(extent, nextExtent)-1)<blockNumber) {
+ countedBlocks += GetExtentSize(extent, nextExtent);
+ continue;
+ }
+
+ currentExtent = extent + nextExtent * sizeofExtent;
+ break;
+ }
+
+ if (extentBuffer == 0) {
+ extentBuffer = malloc(sizeofExtent * extentDensity);
+ if (extentBuffer == 0) return -1;
+ }
+
+ nextExtentBlock = nextExtent / extentDensity;
+ if (currentExtentBlock != nextExtentBlock) {
+ ReadExtentsEntry(extentFile, countedBlocks, extentBuffer);
+ currentExtentBlock = nextExtentBlock;
+ }
+
+ currentExtentSize = GetExtentSize(extentBuffer, nextExtent % extentDensity);
+
+ if ((countedBlocks + currentExtentSize - 1) >= blockNumber) {
+ currentExtent = extentBuffer + sizeofExtent * (nextExtent % extentDensity);
+ break;
+ }
+
+ countedBlocks += currentExtentSize;
+ }
+
+ readOffset = ((blockNumber - countedBlocks) * gBlockSize) +
+ (offset % gBlockSize);
+
+ readSize = GetExtentSize(currentExtent, 0) * gBlockSize - readOffset;
+ if (readSize > (size - sizeRead)) readSize = size - sizeRead;
+
+ readOffset += (long long)GetExtentStart(currentExtent, 0) * gBlockSize;
+
+ CacheRead(gCurrentIH, bufferPos, gAllocationOffset + readOffset,
+ readSize, cache);
+
+ sizeRead += readSize;
+ offset += readSize;
+ bufferPos += readSize;
+ }
+
+ if (extentBuffer) free(extentBuffer);
+
+ return sizeRead;
+}
+
+static long GetExtentStart(void * extents, long index)
+{
+ long start;
+ HFSExtentDescriptor *hfsExtents = extents;
+ HFSPlusExtentDescriptor *hfsPlusExtents = extents;
+
+ if (gIsHFSPlus) start = SWAP_BE32(hfsPlusExtents[index].startBlock);
+ else start = SWAP_BE16(hfsExtents[index].startBlock);
+
+ return start;
+}
+
+static long GetExtentSize(void * extents, long index)
+{
+ long size;
+ HFSExtentDescriptor *hfsExtents = extents;
+ HFSPlusExtentDescriptor *hfsPlusExtents = extents;
+
+ if (gIsHFSPlus) size = SWAP_BE32(hfsPlusExtents[index].blockCount);
+ else size = SWAP_BE16(hfsExtents[index].blockCount);
+
+ return size;
+}
+
+static long CompareHFSCatalogKeys(void * key, void * testKey)
+{
+ HFSCatalogKey *searchKey, *trialKey;
+ long result, searchParentID, trialParentID;
+
+ searchKey = key;
+ trialKey = testKey;
+
+ searchParentID = SWAP_BE32(searchKey->parentID);
+ trialParentID = SWAP_BE32(trialKey->parentID);
+
+ // parent dirID is unsigned
+ if (searchParentID > trialParentID) result = 1;
+ else if (searchParentID < trialParentID) result = -1;
+ else {
+ // parent dirID's are equal, compare names
+ result = FastRelString(searchKey->nodeName, trialKey->nodeName);
+ }
+
+ return result;
+}
+
+static long CompareHFSPlusCatalogKeys(void * key, void * testKey)
+{
+ HFSPlusCatalogKey *searchKey, *trialKey;
+ long result, searchParentID, trialParentID;
+
+ searchKey = key;
+ trialKey = testKey;
+
+ searchParentID = SWAP_BE32(searchKey->parentID);
+ trialParentID = SWAP_BE32(trialKey->parentID);
+
+ // parent dirID is unsigned
+ if (searchParentID > trialParentID) result = 1;
+ else if (searchParentID < trialParentID) result = -1;
+ else {
+ // parent dirID's are equal, compare names
+ if ((searchKey->nodeName.length == 0) || (trialKey->nodeName.length == 0))
+ result = searchKey->nodeName.length - trialKey->nodeName.length;
+ else
+ result = FastUnicodeCompare(&searchKey->nodeName.unicode[0],
+ SWAP_BE16(searchKey->nodeName.length),
+ &trialKey->nodeName.unicode[0],
+ SWAP_BE16(trialKey->nodeName.length));
+ }
+
+ return result;
+}
+
+static long CompareHFSExtentsKeys(void * key, void * testKey)
+{
+ HFSExtentKey *searchKey, *trialKey;
+ long result;
+
+ searchKey = key;
+ trialKey = testKey;
+
+ // assume searchKey < trialKey
+ result = -1;
+
+ if (searchKey->fileID == trialKey->fileID) {
+ // FileNum's are equal; compare fork types
+ if (searchKey->forkType == trialKey->forkType) {
+ // Fork types are equal; compare allocation block number
+ if (searchKey->startBlock == trialKey->startBlock) {
+ // Everything is equal
+ result = 0;
+ } else {
+ // Allocation block numbers differ; determine sign
+ if (SWAP_BE16(searchKey->startBlock) > SWAP_BE16(trialKey->startBlock))
+ result = 1;
+ }
+ } else {
+ // Fork types differ; determine sign
+ if (searchKey->forkType > trialKey->forkType) result = 1;
+ }
+ } else {
+ // FileNums differ; determine sign
+ if (SWAP_BE32(searchKey->fileID) > SWAP_BE32(trialKey->fileID))
+ result = 1;
+ }
+
+ return result;
+}
+
+static long CompareHFSPlusExtentsKeys(void * key, void * testKey)
+{
+ HFSPlusExtentKey *searchKey, *trialKey;
+ long result;
+
+ searchKey = key;
+ trialKey = testKey;
+
+ // assume searchKey < trialKey
+ result = -1;
+
+ if (searchKey->fileID == trialKey->fileID) {
+ // FileNum's are equal; compare fork types
+ if (searchKey->forkType == trialKey->forkType) {
+ // Fork types are equal; compare allocation block number
+ if (searchKey->startBlock == trialKey->startBlock) {
+ // Everything is equal
+ result = 0;
+ } else {
+ // Allocation block numbers differ; determine sign
+ if (SWAP_BE32(searchKey->startBlock) > SWAP_BE32(trialKey->startBlock))
+ result = 1;
+ }
+ } else {
+ // Fork types differ; determine sign
+ if (searchKey->forkType > trialKey->forkType) result = 1;
+ }
+ } else {
+ // FileNums differ; determine sign
+ if (SWAP_BE32(searchKey->fileID) > SWAP_BE32(trialKey->fileID))
+ result = 1;
+ }
+
+ return result;
+}
--- /dev/null
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ File: CaseTables.h
+*/
+
+
+/* The lower case table consists of a 256-entry high-byte table followed by some number of
+ 256-entry subtables. The high-byte table contains either an offset to the subtable for
+ characters with that high byte or zero, which means that there are no case mappings or
+ ignored characters in that block. Ignored characters are mapped to zero.
+ */
+
+u_int16_t gLowerCaseTable[] = {
+
+ // High-byte indices ( == 0 iff no case mapping and no ignorables )
+
+ /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
+
+ // Table 1 (for high byte 0x00)
+
+ /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
+ /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+
+ // Table 2 (for high byte 0x01)
+
+ /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
+ /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
+ /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
+ /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
+ /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
+ /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
+ /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167, 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
+ /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
+ /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
+ /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
+ /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8, 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
+ /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
+ /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
+ /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
+ /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7, 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
+ /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
+
+ // Table 3 (for high byte 0x03)
+
+ /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+ /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+ /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+ /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+ /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+ /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+ /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+ /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
+ /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
+ /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
+ /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
+ /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
+ /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+
+ // Table 4 (for high byte 0x04)
+
+ /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407, 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
+ /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
+ /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
+ /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477, 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
+ /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
+ /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
+ /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
+ /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
+ /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
+ /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7, 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
+ /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7, 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
+ /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
+
+ // Table 5 (for high byte 0x05)
+
+ /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
+ /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+ /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+ /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+ /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
+ /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
+ /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
+ /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+ /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
+ /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
+ /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
+
+ // Table 6 (for high byte 0x10)
+
+ /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
+ /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
+ /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
+ /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
+ /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
+ /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
+ /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
+ /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
+ /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
+ /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
+ /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+ /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+ /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7, 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
+ /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+ /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+ /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
+
+ // Table 7 (for high byte 0x20)
+
+ /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
+ /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
+ /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
+ /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
+ /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
+ /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
+ /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
+ /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
+ /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
+ /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
+ /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
+ /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
+ /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
+ /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
+
+ // Table 8 (for high byte 0x21)
+
+ /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
+ /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
+ /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
+ /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
+ /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
+ /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
+ /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
+ /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
+ /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
+ /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
+ /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
+ /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
+ /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
+ /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
+
+ // Table 9 (for high byte 0xFE)
+
+ /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
+ /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17, 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
+ /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
+ /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37, 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
+ /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47, 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
+ /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57, 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
+ /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67, 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
+ /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
+ /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
+ /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
+ /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
+ /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
+ /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
+ /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
+ /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
+ /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
+
+ // Table 10 (for high byte 0xFF)
+
+ /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
+ /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
+ /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
+ /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
+ /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+ /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+ /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+ /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+ /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
+ /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
+ /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+ /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
+ /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
+ /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
+};
+
+
+/* RelString case folding table */
+
+unsigned short gCompareTable[] = {
+
+ /* 0 */ 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00,
+ /* 1 */ 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, 0x1E00, 0x1F00,
+ /* 2 */ 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, 0x2E00, 0x2F00,
+ /* 3 */ 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, 0x3E00, 0x3F00,
+ /* 4 */ 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, 0x4E00, 0x4F00,
+ /* 5 */ 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, 0x5E00, 0x5F00,
+
+ // 0x60 maps to 'a'
+ // range 0x61 to 0x7a ('a' to 'z') map to upper case
+
+ /* 6 */ 0x4180, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, 0x4E00, 0x4F00,
+ /* 7 */ 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x7B00, 0x7C00, 0x7D00, 0x7E00, 0x7F00,
+
+ // range 0x80 to 0xd8 gets mapped...
+
+ /* 8 */ 0x4108, 0x410C, 0x4310, 0x4502, 0x4E0A, 0x4F08, 0x5508, 0x4182, 0x4104, 0x4186, 0x4108, 0x410A, 0x410C, 0x4310, 0x4502, 0x4584,
+ /* 9 */ 0x4586, 0x4588, 0x4982, 0x4984, 0x4986, 0x4988, 0x4E0A, 0x4F82, 0x4F84, 0x4F86, 0x4F08, 0x4F0A, 0x5582, 0x5584, 0x5586, 0x5508,
+ /* A */ 0xA000, 0xA100, 0xA200, 0xA300, 0xA400, 0xA500, 0xA600, 0x5382, 0xA800, 0xA900, 0xAA00, 0xAB00, 0xAC00, 0xAD00, 0x4114, 0x4F0E,
+ /* B */ 0xB000, 0xB100, 0xB200, 0xB300, 0xB400, 0xB500, 0xB600, 0xB700, 0xB800, 0xB900, 0xBA00, 0x4192, 0x4F92, 0xBD00, 0x4114, 0x4F0E,
+ /* C */ 0xC000, 0xC100, 0xC200, 0xC300, 0xC400, 0xC500, 0xC600, 0x2206, 0x2208, 0xC900, 0x2000, 0x4104, 0x410A, 0x4F0A, 0x4F14, 0x4F14,
+ /* D */ 0xD000, 0xD100, 0x2202, 0x2204, 0x2702, 0x2704, 0xD600, 0xD700, 0x5988, 0xD900, 0xDA00, 0xDB00, 0xDC00, 0xDD00, 0xDE00, 0xDF00,
+
+ /* E */ 0xE000, 0xE100, 0xE200, 0xE300, 0xE400, 0xE500, 0xE600, 0xE700, 0xE800, 0xE900, 0xEA00, 0xEB00, 0xEC00, 0xED00, 0xEE00, 0xEF00,
+ /* F */ 0xF000, 0xF100, 0xF200, 0xF300, 0xF400, 0xF500, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00,
+
+};
--- /dev/null
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * HFSCompare.c - Functions for working with and comparing HFS nams.
+ *
+ * Copyright (c) 1999-2000 Apple Computer, Inc.
+ *
+ * DRI: Josh de Cesare
+ */
+
+#include <sl.h>
+#include "hfs_CaseTables.h"
+
+//_______________________________________________________________________
+//
+// Routine: FastRelString
+//
+// Output: returns -1 if str1 < str2
+// returns 1 if str1 > str2
+// return 0 if equal
+//
+//_______________________________________________________________________
+
+int32_t FastRelString(char * str1, char * str2)
+{
+ int32_t bestGuess;
+ u_int8_t length, length2;
+
+ length = *(str1++);
+ length2 = *(str2++);
+
+ if (length == length2)
+ bestGuess = 0;
+ else if (length < length2)
+ bestGuess = -1;
+ else
+ {
+ bestGuess = 1;
+ length = length2;
+ }
+
+ while (length--)
+ {
+ u_int32_t aChar, bChar;
+
+ aChar = *(str1++);
+ bChar = *(str2++);
+
+ if (aChar != bChar) /* If they don't match exacly, do case conversion */
+ {
+ u_int16_t aSortWord, bSortWord;
+
+ aSortWord = gCompareTable[aChar];
+ bSortWord = gCompareTable[bChar];
+
+ if (aSortWord > bSortWord)
+ return 1;
+
+ if (aSortWord < bSortWord)
+ return -1;
+ }
+
+ /*
+ * If characters match exactly, then go on to next character
+ * immediately without doing any extra work.
+ */
+ }
+
+ /* if you got to here, then return bestGuess */
+ return bestGuess;
+}
+
+
+//
+// FastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
+//
+// IF RESULT
+// --------------------------
+// str1 < str2 => -1
+// str1 = str2 => 0
+// str1 > str2 => +1
+//
+// The lower case table starts with 256 entries (one for each of the upper bytes
+// of the original Unicode char). If that entry is zero, then all characters with
+// that upper byte are already case folded. If the entry is non-zero, then it is
+// the _index_ (not byte offset) of the start of the sub-table for the characters
+// with that upper byte. All ignorable characters are folded to the value zero.
+//
+// In pseudocode:
+//
+// Let c = source Unicode character
+// Let table[] = lower case table
+//
+// lower = table[highbyte(c)]
+// if (lower == 0)
+// lower = c
+// else
+// lower = table[lower+lowbyte(c)]
+//
+// if (lower == 0)
+// ignore this character
+//
+// To handle ignorable characters, we now need a loop to find the next valid character.
+// Also, we can't pre-compute the number of characters to compare; the string length might
+// be larger than the number of non-ignorable characters. Further, we must be able to handle
+// ignorable characters at any point in the string, including as the first or last characters.
+// We use a zero value as a sentinel to detect both end-of-string and ignorable characters.
+// Since the File Manager doesn't prevent the NUL character (value zero) as part of a filename,
+// the case mapping table is assumed to map u+0000 to some non-zero value (like 0xFFFF, which is
+// an invalid Unicode character).
+//
+// Pseudocode:
+//
+// while (1) {
+// c1 = GetNextValidChar(str1) // returns zero if at end of string
+// c2 = GetNextValidChar(str2)
+//
+// if (c1 != c2) break // found a difference
+//
+// if (c1 == 0) // reached end of string on both strings at once?
+// return 0; // yes, so strings are equal
+// }
+//
+// // When we get here, c1 != c2. So, we just need to determine which one is less.
+// if (c1 < c2)
+// return -1;
+// else
+// return 1;
+//
+
+int32_t FastUnicodeCompare( u_int16_t * str1, register u_int32_t length1,
+ u_int16_t * str2, register u_int32_t length2 )
+{
+ register u_int16_t c1,c2;
+ register u_int16_t temp;
+
+ while (1) {
+ /* Set default values for c1, c2 in case there are no more valid chars */
+ c1 = 0;
+ c2 = 0;
+
+ /* Find next non-ignorable char from str1, or zero if no more */
+ while (length1 && c1 == 0) {
+ c1 = SWAP_BE16(*(str1++));
+ --length1;
+ if ((temp = gLowerCaseTable[c1>>8]) != 0) // is there a subtable for this upper byte?
+ c1 = gLowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char
+ }
+
+ /* Find next non-ignorable char from str2, or zero if no more */
+ while (length2 && c2 == 0) {
+ c2 = SWAP_BE16(*(str2++));
+ --length2;
+ if ((temp = gLowerCaseTable[c2>>8]) != 0) // is there a subtable for this upper byte?
+ c2 = gLowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char
+ }
+
+ if (c1 != c2) /* found a difference, so stop looping */
+ break;
+
+ if (c1 == 0) /* did we reach the end of both strings at the same time? */
+ return 0; /* yes, so strings are equal */
+ }
+
+ if (c1 < c2)
+ return -1;
+ else
+ return 1;
+}
+
+
+/*
+ * UTF-8 (UCS Transformation Format)
+ *
+ * The following subset of UTF-8 is used to encode UCS-2 filenames. It
+ * requires a maximum of three 3 bytes per UCS-2 character. Only the
+ * shortest encoding required to represent the significant UCS-2 bits
+ * is legal.
+ *
+ * UTF-8 Multibyte Codes
+ *
+ * Bytes Bits UCS-2 Min UCS-2 Max UTF-8 Byte Sequence (binary)
+ * -------------------------------------------------------------------
+ * 1 7 0x0000 0x007F 0xxxxxxx
+ * 2 11 0x0080 0x07FF 110xxxxx 10xxxxxx
+ * 3 16 0x0800 0xFFFF 1110xxxx 10xxxxxx 10xxxxxx
+ * -------------------------------------------------------------------
+ */
+
+
+/*
+ * utf_encodestr - Encodes the UCS-2 (Unicode) string at ucsp into a
+ * null terminated UTF-8 string at utf8p.
+ *
+ * ucslen is the number of UCS-2 input characters (not bytes)
+ * bufsize is the size of the output buffer in bytes
+ */
+void
+utf_encodestr( const u_int16_t * ucsp, int ucslen,
+ u_int8_t * utf8p, u_int32_t bufsize )
+{
+ u_int8_t *bufend;
+ u_int16_t ucs_ch;
+
+ bufend = utf8p + bufsize;
+
+ while (ucslen-- > 0) {
+ ucs_ch = SWAP_BE16(*ucsp++);
+
+ if (ucs_ch < 0x0080) {
+ if (utf8p >= bufend)
+ break;
+ if (ucs_ch == '\0')
+ continue; /* skip over embedded NULLs */
+ *utf8p++ = ucs_ch;
+
+ } else if (ucs_ch < 0x800) {
+ if ((utf8p + 1) >= bufend)
+ break;
+ *utf8p++ = (ucs_ch >> 6) | 0xc0;
+ *utf8p++ = (ucs_ch & 0x3f) | 0x80;
+
+ } else {
+ if ((utf8p + 2) >= bufend)
+ break;
+ *utf8p++ = (ucs_ch >> 12) | 0xe0;
+ *utf8p++ = ((ucs_ch >> 6) & 0x3f) | 0x80;
+ *utf8p++ = ((ucs_ch) & 0x3f) | 0x80;
+ }
+ }
+
+ *utf8p = '\0';
+}
+
+
+/*
+ * utf_decodestr - Decodes the null terminated UTF-8 string at
+ * utf8p into a UCS-2 (Unicode) string at ucsp.
+ *
+ * ucslen is the number of UCS-2 output characters (not bytes)
+ * bufsize is the size of the output buffer in bytes
+ */
+void utf_decodestr(const u_int8_t * utf8p, u_int16_t * ucsp, u_int16_t * ucslen, u_int32_t bufsize)
+{
+ u_int16_t *bufstart;
+ u_int16_t *bufend;
+ u_int16_t ucs_ch;
+ u_int8_t byte;
+
+ bufstart = ucsp;
+ bufend = (u_int16_t *)((u_int8_t *)ucsp + bufsize);
+
+ while ((byte = *utf8p++) != '\0') {
+ if (ucsp >= bufend)
+ break;
+
+ /* check for ascii */
+ if (byte < 0x80) {
+ ucs_ch = byte;
+
+ *ucsp++ = SWAP_BE16(ucs_ch);
+ continue;
+ }
+
+ switch (byte & 0xf0) {
+ /* 2 byte sequence*/
+ case 0xc0:
+ case 0xd0:
+ /* extract bits 6 - 10 from first byte */
+ ucs_ch = (byte & 0x1F) << 6;
+ break;
+ /* 3 byte sequence*/
+ case 0xe0:
+ /* extract bits 12 - 15 from first byte */
+ ucs_ch = (byte & 0x0F) << 6;
+
+ /* extract bits 6 - 11 from second byte */
+ if (((byte = *utf8p++) & 0xc0) != 0x80)
+ goto stop;
+
+ ucs_ch += (byte & 0x3F);
+ ucs_ch <<= 6;
+ break;
+ default:
+ goto stop;
+ }
+
+ /* extract bits 0 - 5 from final byte */
+ if (((byte = *utf8p++) & 0xc0) != 0x80)
+ goto stop;
+ ucs_ch += (byte & 0x3F);
+
+ *ucsp++ = SWAP_BE16(ucs_ch);
+ }
+stop:
+ *ucslen = SWAP_BE16(ucsp - bufstart);
+}
+++ /dev/null
-/* Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved.
- *
- * PCI Configuration space structure and associated defines.
- *
- * HISTORY
- *
- * 13 May 1994 Dean Reece at NeXT
- * Created.
- *
- */
-
-/* The IOPCIConfigSpace structure can be used to decode the 256 byte
- * configuration space presented by each PCI device. This structure
- * is based on the PCI LOCAL BUS SPECIFICATION, rev 2.1, section 6.1
- */
-
-typedef struct _IOPCIConfigSpace {
- unsigned short VendorID;
- unsigned short DeviceID;
- unsigned short Command;
- unsigned short Status;
- unsigned long RevisionID:8;
- unsigned long ClassCode:24;
- unsigned char CacheLineSize;
- unsigned char LatencyTimer;
- unsigned char HeaderType;
- unsigned char BuiltInSelfTest;
- unsigned long BaseAddress[6];
- unsigned long CardbusCISpointer;
- unsigned short SubVendorID;
- unsigned short SubDeviceID;
- unsigned long ROMBaseAddress;
- unsigned long reserved3;
- unsigned long reserved4;
- unsigned char InterruptLine;
- unsigned char InterruptPin;
- unsigned char MinGrant;
- unsigned char MaxLatency;
- unsigned long VendorUnique[48];
-} IOPCIConfigSpace;
-
-
-/* PCI_DEFAULT_DATA is the value resulting from a read to a non-existent
- * PCI device's configuration space.
- */
-
-#define PCI_DEFAULT_DATA 0xffffffff
-
-
-/* PCI_INVALID_VENDOR_ID is a Vendor ID reserved by the PCI/SIG and is
- * guaranteed not to be assigned to any vendor.
- */
-
-#define PCI_INVALID_VENDOR_ID 0xffff
+++ /dev/null
-/*
- * Mach Operating System
- * Copyright (c) 1989 Carnegie-Mellon University
- * All rights reserved. The CMU software License Agreement specifies
- * the terms and conditions for use and redistribution.
- */
-/*
- * HISTORY
- * $Log: asm.h,v $
- * Revision 1.2 2000/03/07 06:10:59 wsanchez
- * Make main branch like boot-3, which builds.
- *
- * Revision 1.1.2.1 2000/02/29 00:04:34 jliu
- * Added legacy header files.
- *
- * Revision 1.1.1.1 1997/09/30 02:45:05 wsanchez
- * Import of kernel from umeshv/kernel
- *
- * Revision 2.1.1.6 90/03/29 20:45:08 rvb
- * Typo on ENTRY if gprof
- * [90/03/29 rvb]
- *
- * Revision 2.1.1.5 90/02/28 15:47:31 rvb
- * fix SVC for "ifdef wheeze" [kupfer]
- *
- * Revision 2.1.1.4 90/02/27 08:47:30 rvb
- * Fix the GPROF definitions.
- * ENTRY(x) gets profiled iffdef GPROF.
- * Entry(x) (and DATA(x)) is NEVER profiled.
- * MCOUNT can be used by asm that intends to build a frame,
- * after the frame is built.
- * [90/02/26 rvb]
- *
- * Revision 2.1.1.3 90/02/09 17:23:23 rvb
- * Add #define addr16 .byte 0x67
- * [90/02/09 rvb]
- *
- * Revision 2.1.1.2 89/11/10 09:51:33 rvb
- * Added LBi, SVC and ENTRY
- *
- * Revision 2.1.1.1 89/10/22 11:29:38 rvb
- * New a.out and coff compatible .s files.
- * [89/10/16 rvb]
- *
- */
-
-
-#define S_ARG0 4(%esp)
-#define S_ARG1 8(%esp)
-#define S_ARG2 12(%esp)
-#define S_ARG3 16(%esp)
-
-#define FRAME pushl %ebp; movl %esp, %ebp
-#define EMARF leave
-
-#define B_ARG0 8(%ebp)
-#define B_ARG1 12(%ebp)
-#define B_ARG2 16(%ebp)
-#define B_ARG3 20(%ebp)
-
-#define EXT(x) _##x
-#define LBb(x,n) n##b
-#define LBf(x,n) n##f
-
-#define ALIGN 2
-#define LCL(x) x
-
-#define LB(x,n) n
-
-#define SVC .byte 0x9a; .long 0; .word 0x7
-#define String .ascii
-#define Value .word
-
-#define Times(a,b) (a*b)
-#define Divide(a,b) (a/b)
-
-#define INB inb %dx, %al
-#define OUTB outb %al, %dx
-#define INL inl %dx, %eax
-#define OUTL outl %eax, %dx
-
-#define data16 .byte 0x66
-#define addr16 .byte 0x67
-
-
-
-#ifdef GPROF
-#define MCOUNT .data; LB(x, 9): .long 0; .text; lea LBb(x, 9),%edx; call mcount
-#define ENTRY(x) .globl EXT(x); .align ALIGN; EXT(x): ; \
- pushl %ebp; movl %esp, %ebp; MCOUNT; popl %ebp;
-#define ASENTRY(x) .globl x; .align ALIGN; x: ; \
- pushl %ebp; movl %esp, %ebp; MCOUNT; popl %ebp;
-#else /* GPROF */
-#define MCOUNT
-#define ENTRY(x) .globl EXT(x); .align ALIGN; EXT(x):
-#define ASENTRY(x) .globl x; .align ALIGN; x:
-#endif /* GPROF */
-
-#define Entry(x) .globl EXT(x); .align ALIGN; EXT(x):
-#define DATA(x) .globl EXT(x); .align ALIGN; EXT(x):
-
+++ /dev/null
-/* @(#)disk.h 1.0 08/29/87 (c) 1987 NeXT */
-
-/*
- * HISTORY
- * 28-Mar-92 Doug Mitchell
- * Moved disk_label struct to <bsd/dev/disk_label.h>.
- *
- * 22-May-91 Gregg Kellogg (gk) at NeXT
- * Split out public interface.
- *
- * 20-Jul-90 Doug Mitchell
- * Added DKIOCSFORMAT, DKIOCGFORMAT
- *
- * 16-Apr-90 Doug Mitchell at NeXT
- * Added DKIOCPANELPRT.
- *
- * 25-Mar-90 John Seamons (jks) at NeXT
- * Removed obsolete DKIOCNOTIFY and DKIOCINSERT.
- *
- * 23-Mar-90 Doug Mitchell
- * Added DKIOCEJECT.
- *
- * 14-Feb-90 Doug Mitchell at NeXT
- * Added DKIOCMNOTIFY.
- *
- * 16-Mar-88 John Seamons (jks) at NeXT
- * Cleaned up to support standard disk label definitions.
- *
- * 24-Feb-88 Mike DeMoney (mike) at NeXT
- * Added defines for dl_bootfile and dl_boot0_blkno.
- * Reduced NBAD to allow for these entries in disktab.
- *
- * 29-Aug-87 John Seamons (jks) at NeXT
- * Created.
- *
- */
-
-#ifndef _BSD_DEV_DISK_
-#define _BSD_DEV_DISK_
-
-#include <mach/machine/vm_types.h>
-#include <mach/machine/boolean.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <bsd/dev/disk_label.h>
-
-#define DR_CMDSIZE 32
-#define DR_ERRSIZE 32
-
-struct disk_req {
- int dr_bcount; /* byte count for data transfers */
- caddr_t dr_addr; /* memory addr for data transfers */
- struct timeval dr_exec_time; /* execution time of operation */
-
- /*
- * interpretation of cmdblk and errblk is driver specific.
- */
- char dr_cmdblk[DR_CMDSIZE];
- char dr_errblk[DR_ERRSIZE];
-};
-
-struct sdc_wire {
- vm_offset_t start, end;
- boolean_t new_pageable;
-};
-
-
-#define BAD_BLK_OFF 4 /* offset of bad blk tbl from label */
-#define NBAD_BLK (12 * 1024 / sizeof (int))
-
-struct bad_block { /* bad block table, sized to be 12KB */
- int bad_blk[NBAD_BLK];
-};
-
-/*
- * sector bitmap states (2 bits per sector)
- */
-#define SB_UNTESTED 0 /* must be zero */
-#define SB_BAD 1
-#define SB_WRITTEN 2
-#define SB_ERASED 3
-
-struct drive_info { /* info about drive hardware */
- char di_name[MAXDNMLEN]; /* drive type name */
- int di_label_blkno[NLABELS];/* label loc'ns in DEVICE SECTORS */
- int di_devblklen; /* device sector size */
- int di_maxbcount; /* max bytes per transfer request */
-};
-
-#define DS_STATSIZE 32
-
-struct disk_stats {
- int s_ecccnt; /* avg ECC corrections per sector */
- int s_maxecc; /* max ECC corrections observed */
-
- /*
- * interpretation of s_stats is driver specific
- */
- char s_stats[DS_STATSIZE];
-};
-
-struct drive_location {
- char location[ 128 ];
-};
-
-#define DKIOCGLABEL _IOR('d', 0,struct disk_label) // read label
-#define DKIOCSLABEL _IOW('d', 1,struct disk_label) // write label
-#define DKIOCGBITMAP _IO('d', 2) // read bitmap
-#define DKIOCSBITMAP _IO('d', 3) // write bitmap
-#define DKIOCREQ _IOWR('d', 4, struct disk_req) // cmd request
-#define DKIOCINFO _IOR('d', 5, struct drive_info) // get drive info
-#define DKIOCZSTATS _IO('d',7) // zero statistics
-#define DKIOCGSTATS _IO('d', 8) // get statistics
-#define DKIOCRESET _IO('d', 9) // reset disk
-#define DKIOCGFLAGS _IOR('d', 11, int) // get driver flags
-#define DKIOCSFLAGS _IOW('d', 12, int) // set driver flags
-#define DKIOCSDCWIRE _IOW('d', 14, struct sdc_wire) // sdc wire memory
-#define DKIOCSDCLOCK _IO('d', 15) // sdc lock
-#define DKIOCSDCUNLOCK _IO('d', 16) // sdc unlock
-#define DKIOCGFREEVOL _IOR('d', 17, int) // get free volume #
-#define DKIOCGBBT _IO('d', 18) // read bad blk tbl
-#define DKIOCSBBT _IO('d', 19) // write bad blk tbl
-#define DKIOCMNOTIFY _IOW('d', 20, int) // message on insert
-#define DKIOCEJECT _IO('d', 21) // eject disk
-#define DKIOCPANELPRT _IOW('d', 22, int) // register Panel
- // Request port
-#define DKIOCSFORMAT _IOW('d', 23, int) // set 'Formatted' flag
-#define DKIOCGFORMAT _IOR('d', 23, int) // get 'Formatted' flag
-#define DKIOCBLKSIZE _IOR('d', 24, int) // device sector size
-#define DKIOCNUMBLKS _IOR('d', 25, int) // number of sectors
-#define DKIOCCHECKINSERT _IO('d',26) // manually poll removable
- // media drive
-#define DKIOCCANCELAUTOMOUNT _IOW('d',27, dev_t) // cancel automount request
-#define DKIOCGLOCATION _IOR('d',28, struct drive_location) // arch dependent location descrip
-#endif /* _BSD_DEV_DISK_ */
-
+++ /dev/null
-/*
- * Copyright (c) 1992 NeXT Computer, Inc.
- *
- * IBM PC disk partitioning data structures.
- *
- * HISTORY
- *
- * 8 July 1992 David E. Bohman at NeXT
- * Created.
- */
-
-#ifdef DRIVER_PRIVATE
-
-#define DISK_BLK0 0 /* blkno of boot block */
-#define DISK_BLK0SZ 512 /* size of boot block */
-#define DISK_BOOTSZ 446 /* size of boot code in boot block */
-#define DISK_SIGNATURE 0xAA55 /* signature of the boot record */
-#define FDISK_NPART 4 /* number of entries in fdisk table */
-#define FDISK_ACTIVE 0x80 /* indicator of active partition */
-#define FDISK_NEXTNAME 0xA7 /* indicator of NeXT partition */
-#define FDISK_DOS12 0x01 /* 12-bit fat < 10MB dos partition */
-#define FDISK_DOS16S 0x04 /* 16-bit fat < 32MB dos partition */
-#define FDISK_DOSEXT 0x05 /* extended dos partition */
-#define FDISK_DOS16B 0x06 /* 16-bit fat >= 32MB dos partition */
-
-/*
- * Format of fdisk partion entry (if present).
- */
-struct fdisk_part {
- unsigned char bootid; /* bootable or not */
- unsigned char beghead; /* begining head, sector, cylinder */
- unsigned char begsect; /* begcyl is a 10-bit number */
- unsigned char begcyl; /* High 2 bits are in begsect */
- unsigned char systid; /* OS type */
- unsigned char endhead; /* ending head, sector, cylinder */
- unsigned char endsect; /* endcyl is a 10-bit number */
- unsigned char endcyl; /* High 2 bits are in endsect */
- unsigned long relsect; /* partion physical offset on disk */
- unsigned long numsect; /* number of sectors in partition */
-};
-
-/*
- * Format of boot block.
- */
-struct disk_blk0 {
- unsigned char bootcode[DISK_BOOTSZ];
- unsigned char parts[FDISK_NPART][sizeof (struct fdisk_part)];
- unsigned short signature;
-};
-
-#endif /* DRIVER_PRIVATE */
#define __LIBSAIO_LIBSAIO_H
#include "libsa.h"
-#include "saio.h"
+#include "memory.h"
+#include "kernBootStruct.h"
+#include "io_inline.h"
#include "saio_types.h"
#include "saio_internal.h"
-#endif /* !__LIBSAIO_LIBSAIO_H */
\ No newline at end of file
+#endif /* !__LIBSAIO_LIBSAIO_H */
*/
#include "libsaio.h"
-#include "memory.h"
-#include "kernBootStruct.h"
#include "rcz_common.h"
-#include <ufs/ufs/dir.h>
+#include "rcz_decompress_file.h"
#include <mach-o/fat.h>
-static int devMajor[3] = { 6, 3, 1 }; // sd, hd, fd major dev #'s
+static int devMajor[3] = { 6, 3, 1 }; // sd, hd, fd major dev #'s
+
+static int xread(int fd, char * addr, int size);
+static int loadmacho(struct mach_header * head, int dev, int io,
+ entry_t * rentry, char ** raddr, int * rsize,
+ int file_offset);
//==========================================================================
// Open a file for reading. If the file doesn't exist,
// try opening the compressed version.
#ifdef RCZ_COMPRESSED_FILE_SUPPORT
-int
-openfile(char *filename, int ignored)
+int openfile(const char * filename, int ignored)
{
unsigned char *buf;
int fd, size, ret;
unsigned char *addr;
-
+
if ((fd = open(filename, 0)) < 0) {
- buf = malloc(256);
- sprintf(buf, "%s%s", filename, RCZ_EXTENSION);
- if ((fd = open(buf, 0)) >= 0) {
- size = rcz_file_size(fd);
- addr = (unsigned char *)((KERNEL_ADDR + KERNEL_LEN) - size);
- ret = rcz_decompress_file(fd, addr);
- close(fd);
- if (ret < 0)
- fd = -1;
- else
- fd = openmem(addr, size);
- }
- free(buf);
+ buf = malloc(256);
+ sprintf(buf, "%s%s", filename, RCZ_EXTENSION);
+ if ((fd = open(buf, 0)) >= 0) {
+ size = rcz_file_size(fd);
+ addr = (unsigned char *)((KERNEL_ADDR + KERNEL_LEN) - size);
+ ret = rcz_decompress_file(fd, addr);
+ close(fd);
+ if (ret < 0)
+ fd = -1;
+ else
+ fd = openmem(addr, size);
+ }
+ free(buf);
}
return fd;
}
#else
-int
-openfile(char *filename, int ignored)
+int openfile(char * filename, int ignored)
{
return open(filename, 0);
}
//==========================================================================
// loadprog
-int
-loadprog( int dev,
- int fd,
- struct mach_header * headOut,
- entry_t * entry, /* entry point */
- char ** addr, /* load address */
- int * size ) /* size of loaded program */
+int loadprog( int dev, int fd, struct mach_header * headOut,
+ entry_t * entry, /* entry point */
+ char ** addr, /* load address */
+ int * size ) /* size of loaded program */
{
struct mach_header head;
int file_offset = 0;
else if ( file_offset == 0 &&
((head.magic == FAT_CIGAM) || (head.magic == FAT_MAGIC)) )
{
- int swap = (head.magic == FAT_CIGAM) ? 1 : 0;
- struct fat_header * fhp = (struct fat_header *) &head;
- struct fat_arch * fap;
- int i, narch = swap ? NXSwapLong(fhp->nfat_arch) : fhp->nfat_arch;
- int cpu, size;
- char * buf;
-
- size = sizeof(struct fat_arch) * narch;
- buf = malloc(size);
+ int swap = (head.magic == FAT_CIGAM) ? 1 : 0;
+ struct fat_header * fhp = (struct fat_header *) &head;
+ struct fat_arch * fap;
+ int i, narch = swap ? NXSwapLong(fhp->nfat_arch) : fhp->nfat_arch;
+ int cpu, size;
+ char * buf;
+
+ size = sizeof(struct fat_arch) * narch;
+ buf = malloc(size);
b_lseek(fd, 0, 0);
read(fd, buf, size);
-
+
for ( i = 0, fap = (struct fat_arch *)(buf+sizeof(struct fat_header));
i < narch;
i++, fap++ )
//
// Read from file descriptor. addr is a physical address.
-int xread( int fd,
- char * addr,
- int size )
+static int xread( int fd, char * addr, int size )
{
- char * orgaddr = addr;
- long offset;
- unsigned count;
- long max;
+ char * orgaddr = addr;
+ long offset;
+ unsigned count;
+ long max;
#define BUFSIZ 8192
- char * buf;
- int bufsize = BUFSIZ;
+ char * buf;
+ int bufsize = BUFSIZ;
#if 0
printf("xread: addr=%x, size=%x\n", addr, size);
sleep(1);
#endif
- buf = malloc(BUFSIZ);
-
- // align your read to increase speed
- offset = tell(fd) & 4095;
- if ( offset != 0 )
- max = 4096 - offset;
- else
- max = bufsize;
-
- while ( size > 0 )
- {
- if ( size > max ) count = max;
- else count = size;
+ buf = malloc(BUFSIZ);
+
+ // align your read to increase speed
+ offset = tell(fd) & 4095;
+ if ( offset != 0 )
+ max = 4096 - offset;
+ else
+ max = bufsize;
+
+ while ( size > 0 )
+ {
+ if ( size > max ) count = max;
+ else count = size;
#if 0
- printf("xread: loop size=%x, count=%x\n", size, count);
- sleep(1);
+ printf("xread: loop size=%x, count=%x\n", size, count);
+ sleep(1);
#endif
- if ( read(fd, buf, count) != count) break;
+ if ( read(fd, buf, count) != count) break;
- bcopy(buf, ptov(addr), count);
- size -= count;
- addr += count;
+ bcopy(buf, ptov(addr), count);
+ size -= count;
+ addr += count;
- max = bufsize;
+ max = bufsize;
#if 0
- tick += count;
- if ( tick > (50*1024) )
- {
- putchar('+');
- tick = 0;
- }
+ tick += count;
+ if ( tick > (50*1024) )
+ {
+ putchar('+');
+ tick = 0;
+ }
#endif
- }
+ }
- free(buf);
- return addr-orgaddr;
+ free(buf);
+ return addr-orgaddr;
}
//==========================================================================
// loadmacho
-int
-loadmacho( struct mach_header * head,
- int dev,
- int io,
- entry_t * rentry,
- char ** raddr,
- int * rsize,
- int file_offset )
+static int loadmacho( struct mach_header * head, int dev, int io,
+ entry_t * rentry, char ** raddr, int * rsize,
+ int file_offset )
{
- int ncmds;
- void * cmds;
+ int ncmds;
+ void * cmds;
void * cp;
- unsigned int entry = 0;
- int vmsize = 0;
- unsigned int vmaddr = ~0;
+ unsigned int entry = 0;
+ int vmsize = 0;
+ unsigned int vmaddr = ~0;
unsigned int vmend = 0;
- struct xxx_thread_command {
- unsigned long cmd;
- unsigned long cmdsize;
- unsigned long flavor;
- unsigned long count;
- i386_thread_state_t state;
- } * th;
+ struct xxx_thread_command {
+ unsigned long cmd;
+ unsigned long cmdsize;
+ unsigned long flavor;
+ unsigned long count;
+ i386_thread_state_t state;
+ } * th;
- // XXX should check cputype
- cmds = malloc(head->sizeofcmds);
- b_lseek(io, sizeof(struct mach_header) + file_offset, 0);
+ // XXX should check cputype
+ cmds = malloc(head->sizeofcmds);
+ b_lseek(io, sizeof(struct mach_header) + file_offset, 0);
- if ( read(io, (char *) cmds, head->sizeofcmds) != head->sizeofcmds )
+ if ( read(io, (char *) cmds, head->sizeofcmds) != head->sizeofcmds )
{
- error("loadmacho: error reading commands\n");
- goto shread;
- }
+ error("loadmacho: error reading commands\n");
+ goto shread;
+ }
- for ( ncmds = head->ncmds, cp = cmds; ncmds > 0; ncmds-- )
- {
- unsigned int addr;
+ for ( ncmds = head->ncmds, cp = cmds; ncmds > 0; ncmds-- )
+ {
+ unsigned int addr;
-#define lcp ((struct load_command *) cp)
-#define scp ((struct segment_command *) cp)
+#define lcp ((struct load_command *) cp)
+#define scp ((struct segment_command *) cp)
- switch ( lcp->cmd )
- {
+ switch ( lcp->cmd )
+ {
case LC_SEGMENT:
addr = (scp->vmaddr & 0x3fffffff) + (int)*raddr;
if ( scp->filesize )
// FIXME: check to see if we overflow
// the available space (should be passed in
// as the size argument).
-
+
#if 0
printf("LC: fileoff %x, filesize %x, off %x, addr %x\n",
scp->fileoff, scp->filesize, file_offset, addr);
th = (struct xxx_thread_command *) cp;
entry = th->state.eip;
break;
- }
- cp += lcp->cmdsize;
- }
+ }
+ cp += lcp->cmdsize;
+ }
- kernBootStruct->rootdev = (dev & 0xffffff00) | devMajor[Dev(dev)];
+ kernBootStruct->rootdev = (dev & 0xffffff00) | devMajor[B_TYPE(dev)];
- free(cmds);
+ free(cmds);
- *rentry = (entry_t)( (int) entry & 0x3fffffff );
- *rsize = vmend - vmaddr;
- *raddr = (char *)vmaddr;
+ *rentry = (entry_t)( (int) entry & 0x3fffffff );
+ *rsize = vmend - vmaddr;
+ *raddr = (char *)vmaddr;
- return 0;
+ return 0;
shread:
- free(cmds);
- return -1;
+ free(cmds);
+ return -1;
}
* All rights reserved.
*/
-#include "io_inline.h"
#include "libsaio.h"
/*
void enableA20()
{
- /* make sure that the input buffer is empty */
- while (inb(PORT_B) & KB_INFULL);
+ /* make sure that the input buffer is empty */
+ while (inb(PORT_B) & KB_INFULL);
- /* make sure that the output buffer is empty */
- if (inb(PORT_B) & KB_OUTFULL)
- (void)inb(PORT_A);
+ /* make sure that the output buffer is empty */
+ if (inb(PORT_B) & KB_OUTFULL)
+ (void)inb(PORT_A);
- /* make sure that the input buffer is empty */
- while (inb(PORT_B) & KB_INFULL);
+ /* make sure that the input buffer is empty */
+ while (inb(PORT_B) & KB_INFULL);
- /* write output port */
- outb(PORT_B, CMD_WOUT);
+ /* write output port */
+ outb(PORT_B, CMD_WOUT);
- /* wait until command is accepted */
- while (inb(PORT_B) & KB_INFULL);
+ /* wait until command is accepted */
+ while (inb(PORT_B) & KB_INFULL);
- outb(PORT_A, KB_A20);
+ outb(PORT_A, KB_A20);
- while (inb(PORT_B) & KB_INFULL); /* wait until done */
+ while (inb(PORT_B) & KB_INFULL); /* wait until done */
}
void sleep(int n)
{
- int endtime = (time18() + 18*n);
- while (time18() < endtime);
+ int endtime = (time18() + 18*n);
+ while (time18() < endtime);
}
void turnOffFloppy(void)
{
- /*
- * Disable floppy:
- * Hold controller in reset,
- * disable DMA and IRQ,
- * turn off floppy motors.
- */
- outb(0x3F2, 0x00);
+ /*
+ * Disable floppy:
+ * Hold controller in reset,
+ * disable DMA and IRQ,
+ * turn off floppy motors.
+ */
+ outb(0x3F2, 0x00);
}
-char * newString(char * oldString)
+char * newString(const char * oldString)
{
if ( oldString )
return strcpy(malloc(strlen(oldString)+1), oldString);
else
return NULL;
}
+
+void stop(const char * msg)
+{
+ error("\n%s\n", msg);
+ halt();
+}
*/
#include "libsaio.h"
-#include "nbp.h"
+
+/*
+ * Convert zero-based linear address to far pointer.
+ */
+#define GET_FP(x) ( (((x) & 0xffff0000) << (16 - 4)) | ((x) & 0xffff) )
/*==========================================================================
* Issue a command to the network loader.
* ensure that it resides within the addressable range for the
* network loader, which runs in real mode.
*/
-UInt32
-nbp(nbpCommandCode_t code, nbpCommand_u * cmd)
+static UInt32 nbp(nbpCommandCode_t code, nbpCommand_u * cmd)
{
loader(code, GET_FP((UInt32) cmd));
}
/*==========================================================================
- * Execute a TFTP Read File command.
- *
+ * Unload Base Code Stack command.
+ */
+UInt32 nbpUnloadBaseCode()
+{
+ return nbp(nbpCommandUnloadBaseCode, (nbpCommand_u *) 0);
+}
+
+/*==========================================================================
+ * TFTP Read File command.
*/
-UInt32 nbpTFTPReadFile(UInt8 * filename, // name of the file
- UInt32 * bufferSize, // [IN] size limit, [OUT} real size
- UInt32 bufferAddr) // physical address
+static long NBPLoadFile(CICell ih, char * filePath)
{
nbpCommandTFTPReadFile_s cmd;
UInt32 ret;
- strcpy(cmd.filename, filename);
+ strcpy(cmd.filename, filePath);
cmd.status = nbpStatusFailed;
- cmd.bufferSize = *bufferSize;
- cmd.buffer = bufferAddr;
+ cmd.bufferSize = TFTP_LEN;
+ cmd.buffer = TFTP_ADDR;
- ret = nbp(nbpCommandTFTPReadFile, (nbpCommand_u *) &cmd);
+ verbose("Loading file: %s\n", filePath);
- *bufferSize = cmd.bufferSize; // bytes transferred
+ ret = nbp(nbpCommandTFTPReadFile, (nbpCommand_u *) &cmd);
- return ret;
+ return (ret == nbpStatusSuccess) ? cmd.bufferSize : -1;
}
/*==========================================================================
- * Execute an Unload Base Code Stack command.
- *
+ * GetDirEntry is not supported.
*/
-UInt32 nbpUnloadBaseCode()
+static long NBPGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time)
{
- return nbp(nbpCommandUnloadBaseCode, (nbpCommand_u *) 0);
+ return -1;
+}
+
+//==========================================================================
+
+static void NBPGetDescription(CICell ih, char * str, long strMaxLen)
+{
+ sprintf( str, "Ethernet PXE Client" );
+}
+
+//==========================================================================
+
+BVRef nbpScanBootVolumes( int biosdev, int * countPtr )
+{
+ static BVRef gNetBVR = NULL;
+
+ if ( countPtr ) *countPtr = 1;
+
+ if ( !gNetBVR )
+ {
+ gNetBVR = malloc( sizeof(*gNetBVR) );
+ if ( gNetBVR )
+ {
+ bzero(gNetBVR, sizeof(*gNetBVR));
+ gNetBVR->biosdev = biosdev;
+ gNetBVR->flags = kBVFlagPrimary | kBVFlagNativeBoot;
+ gNetBVR->description = NBPGetDescription;
+ gNetBVR->fs_loadfile = NBPLoadFile;
+ gNetBVR->fs_getdirentry = NBPGetDirEntry;
+ }
+ }
+
+ return gNetBVR;
}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __LIBSAIO_NBP_H
-#define __LIBSAIO_NBP_H
-
-#include "nbp_cmd.h"
-
-/*==========================================================================
- * Call the network loader's exported entry point.
- * Function is in asm.s.
- */
-extern void loader(UInt32 code, UInt32 cmdptr);
-
-/*==========================================================================
- * Convert zero-based linear address to far pointer.
- */
-#define GET_FP(x) ( (((x) & 0xffff0000) << (16 - 4)) | \
- ((x) & 0xffff) )
-
-/*==========================================================================
- * Issue a command to the network loader.
- */
-extern UInt32 nbp(nbpCommandCode_t code, nbpCommand_u * cmd);
-
-/*==========================================================================
- * Execute a TFTP Read File command.
- */
-extern UInt32 nbpTFTPReadFile(UInt8 * filename,
- UInt32 * bufferSize,
- UInt32 bufferAddr);
-
-/*==========================================================================
- * Execute an Unload Base Code Stack command.
- */
-extern UInt32 nbpUnloadBaseCode();
-
-#endif /* !__LIBSAIO_NBP_H */
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1990 Carnegie-Mellon University
- * Copyright (c) 1989 Carnegie-Mellon University
- * All rights reserved. The CMU software License Agreement specifies
- * the terms and conditions for use and redistribution.
- */
-
-// INTEL CORPORATION PROPRIETARY INFORMATION
-//
-// This software is supplied under the terms of a license agreement or
-// nondisclosure agreement with Intel Corporation and may not be copied
-// nor disclosed except in accordance with the terms of that agreement.
-//
-// Copyright 1988 Intel Corporation
-// Copyright 1988, 1989 by Intel Corporation
-//
-
- .file "bios.s"
-
-#include <machdep/i386/asm.h>
-#include "memory.h"
-
- .text
-
-#if 0
-// biosread(dev, cyl, head, sec, num)
-// Read num sectors from disk into the internal buffer "intbuf" which
-// is the first 4K bytes of the boot loader.
-// BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
-// Call with %ah = 0x2
-// %al = number of sectors
-// %ch = cylinder
-// %cl = sector
-// %dh = head
-// %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
-// %es:%bx = segment:offset of buffer
-// Return:
-// %al = 0x0 on success; err code on failure
-
-ENTRY(_biosread)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-// push %fs
-// push %gs
-
- movb 0x10(%ebp), %dh // head
-
- movw 0x0c(%ebp), %cx
- xchgb %ch, %cl // cylinder; %cl=the high 2 bits of cyl
- rorb $2, %cl
- movb 0x14(%ebp), %al
- orb %al, %cl
- incb %cl // sector; sec starts from 1, not 0
-
- movb 0x8(%ebp), %dl // device
- movb 0x18(%ebp),%bl // number of sectors
- movb $2,%bh // bios read function
-
- call EXT(_prot_to_real) // enter real mode, set %es to BOOTSEG
-
- data16
- mov $5,%edi // retry up to 5 times
-
-retry_disc:
- mov %ebx,%eax // get function and amount
-// xor %ebx, %ebx // offset = 0
- data16
- mov $(ptov(BIOS_ADDR)), %ebx
-
- push %eax // save amount
- push %ecx
- push %edx
- push %edi
- int $0x13
- pop %edi
- pop %edx
- pop %ecx
- pop %ebx // pop amount into bx (safe place)
-
-// test $0, %ah
- data16
- jnb read_succes
-
- // woops, bios failed to read sector
- push %eax // save error
- xor %eax,%eax
- int $0x13 // reset disk
- pop %eax // restore error code
- dec %edi
- data16
- jne retry_disc
-
-read_succes:
- mov %eax, %ebx // save return value
-
- data16
- call EXT(_real_to_prot) // back to protected mode
-
- xor %ax, %ax
- movb %bh, %al // return value in %ax
-
-// pop %gs
-// pop %fs
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
-
- ret
-
-// putc(ch)
-// BIOS call "INT 10H Function 0Eh" to write character to console
-// Call with %ah = 0x0e
-// %al = character
-// %bh = page
-// %bl = foreground color ( graphics modes)
-
-
-ENTRY(_putc)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- movb 0x8(%ebp), %cl
-
- call EXT(_prot_to_real)
-
-// data16
-// mov $0x13, %ebx // colors in 2 bit palette, grey and white
-// mov $0x1, %ebx // %bh=0, %bl=1 (blue)
-//
-// movb $1,%bh // background gray
- movb $0,%bh // background gray
- movb $3,%bl // foreground white in 2 bit palette
-
- movb $0xe, %ah
- movb %cl, %al
-
- int $0x10 // display a byte
-
- data16
- call EXT(_real_to_prot)
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-ENTRY(cputc)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- movb 0x8(%ebp), %cl
- movb 0x12(%ebp), %bl
-
- call EXT(_prot_to_real)
-
- movb $0,%bh // page 0
-
- movb %cl, %al
- movb $0x9, %ah
- movb $1, %cx
-
- int $0x10 // display a byte
-
- data16
- call EXT(_real_to_prot)
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-// bgetc()
-// BIOS call "INT 16H Function 00H" to read character from keyboard
-// Call with %ah = 0x0
-// Return: %ah = keyboard scan code
-// %al = ASCII character
-
-ENTRY(bgetc)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- call EXT(_prot_to_real)
-
- movb $0, %ah
-
- int $0x16
-
- mov %eax, %ebx // _real_to_prot uses %eax
-
- data16
- call EXT(_real_to_prot)
-
- xor %eax, %eax
- mov %bx, %ax
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-// readKeyboardStatus()
-// if there is a character pending, return it; otherwise return 0
-// BIOS call "INT 16H Function 01H" to check whether a character is pending
-// Call with %ah = 0x1
-// Return:
-// If key waiting to be input:
-// %ah = keyboard scan code
-// %al = ASCII character
-// Zero flag = clear
-// else
-// Zero flag = set
-
-ENTRY(_readKeyboardStatus)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- call EXT(_prot_to_real) // enter real mode
-
- xor %ebx, %ebx
- movb $0x1, %ah
- int $0x16
-
- data16
- jz nochar
-
- movw %ax, %bx
-
-nochar:
- data16
- call EXT(_real_to_prot)
-
- xor %eax, %eax
- movw %bx, %ax
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-
-// time in 18ths of a second
-ENTRY(_time18)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- call EXT(_prot_to_real) // enter real mode
-
- xor %bx, %bx
- xor %eax, %eax
- int $0x1a
-
- mov %edx,%ebx
- shl $16,%cx // shifts ecx
- or %cx,%bx // %ebx has 32 bit time
-
- data16
- call EXT(_real_to_prot)
-
- mov %ebx,%eax
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-//
-// get_diskinfo(): return a word that represents the
-// max number of sectors and heads and drives for this device
-//
-
-ENTRY(_get_diskinfo)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- movb 0x8(%ebp), %dl // diskinfo(drive #)
- call EXT(_prot_to_real) // enter real mode
-
- movb $0x8, %ah // ask for disk info
- int $0x13
-
- data16
- call EXT(_real_to_prot) // back to protected mode
-
-// form a longword representing all this gunk
- mov %ecx, %eax
- shrb $6, %al
- andb $0x03, %al
- xchgb %ah, %al // ax has max cyl
- shl $16, %eax
-
- movb %dh, %ah // # heads
- andb $0x3f, %cl // mask of cylinder gunk
- movb %cl, %al // # sectors
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-#endif
-#if 0
-//
-// getEisaInfo(<slot>): return an int that represents the
-// vendor id for the specified slot (0 < slot < 64)
-// returns 0 for any error
-// returns bytes in the order [0 1 2 3] in %eax;
-
-ENTRY(getEisaInfo)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- movb 0x8(%ebp), %cl // slot #
- call EXT(_prot_to_real) // enter real mode
-
- movb $0,%al
- movb $0xd8, %ah // eisa slot info
- int $0x15
-
- data16
- call EXT(_real_to_prot) // back to protected mode
-
- movb %ah,%bl
- xor %eax,%eax
-
- test $0,%bl
- jne eisaerr
-
-// form a longword representing all this gunk
- mov %esi, %eax
- shl $16, %eax
- mov %di,%ax
- bswap %eax
-
-eisaerr:
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-#endif
-
-#if 0
-//
-// memsize(i) : return the memory size in KB. i == 0 for conventional memory,
-// i == 1 for extended memory
-// BIOS call "INT 12H" to get conventional memory size
-// BIOS call "INT 15H, AH=88H" to get extended memory size
-// Both have the return value in AX.
-//
-
-ENTRY(_memsize)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- mov 8(%ebp), %ebx
- call EXT(_prot_to_real) // enter real mode
- cmpb $0x1, %bl
- data16
- je xext
- int $0x12
- data16
- jmp xdone
-xext:
- movb $0x88, %ah
- int $0x15
-xdone:
- mov %eax, %ebx
- data16
- call EXT(_real_to_prot)
- xor %eax, %eax
- mov %ebx, %eax
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-
-// video_mode(mode)
-// BIOS call "INT 10H Function 0h" to set vga graphics mode
-
-
-ENTRY(_video_mode)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- movb 0x8(%ebp), %cl
-
- call EXT(_prot_to_real)
-
- movb $0, %ah
- movb %cl, %al
-
- int $0x10 // display a byte
-
- data16
- call EXT(_real_to_prot)
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-
-
-
-// setCursorPosition(x,y)
-// BIOS call "INT 10H Function 2" to set cursor position
-
-
-ENTRY(_setCursorPosition)
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %ecx
- push %edx
- push %esi
- push %edi
- push %ds
- push %es
-
- movb 0x8(%ebp), %cl
- movb 0xc(%ebp), %ch
-
- call EXT(_prot_to_real)
-
- movb $2, %ah // setcursor function
- movb $0, %bh // page num 0 for graphics
- movb %cl, %dl // column, x
- movb %ch, %dh // row, y
-
- int $0x10 // set cursor
-
- data16
- call EXT(_real_to_prot)
-
- pop %es
- pop %ds
- pop %edi
- pop %esi
- pop %edx
- pop %ecx
- pop %ebx
-
- pop %ebp
- ret
-#endif
-
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#import "libsa.h"
-#import "libsaio.h"
-
-void *sh_malloc(size_t size) {return malloc(size);}
-void sh_free(void *start) { free(start); }
-void *sh_realloc(void *ptr, size_t size) {return realloc(ptr,size);}
+++ /dev/null
-/*
- * string table functions.
- */
-
-#import "saio_types.h"
-
-extern char *
-newStringFromList(
- char **list,
- int *size
-);
-extern int stringLength(char *table, int compress);
-extern BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size);
-extern char *newStringForStringTableKey(
- char *table,
- char *key
-);
-extern BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len);
-extern BOOL getValueForKey(
- char *key,
- char **val,
- int *size
-);
-extern char *
-loadLocalizableStrings(
- char *name
-);
-extern char *
-bundleLongName(
- char *bundleName
-);
-extern loadConfigFile( char *configFile, char **table, int allocTable);
-extern int
-loadConfigDir(
- char *bundleName, // bundle directory name (e.g. "System.config")
- int useDefault, // use Default.table instead of instance tables
- char **table, // returns pointer to config table
- int allocTable // zalloc the table and return in *table
-);
-extern loadSystemConfig(
- char *which,
- int size
-);
-extern int
-loadOtherConfigs(
- int useDefault
-);
-
-
-
-
-
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1993 NeXT, Inc.
- * All rights reserved.
- */
-
-#import "libsaio.h"
-#import "kernBootStruct.h"
-#import "stringConstants.h"
-#import <driverkit/configTablePrivate.h>
-
-extern KERNBOOTSTRUCT *kernBootStruct;
-extern char *Language;
-extern char *LoadableFamilies;
-
-
-static char_ret
-getachar(
- char **string_p
-)
-{
- register char *str = *string_p;
- register int c;
- char_ret r;
-
- c = *str++;
- if (c == '\\') {
- r.quoted = YES;
- c = *str++;
- switch(c) {
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- default:
- break;
- }
- } else {
- r.quoted = NO;
- }
- *string_p = str;
- r.c = c;
- return r;
-}
-
-/*
- * A token is:
- * <non_space_non_semicolon>*
- * "<non_quote>*"
- * <semicolon>
- */
-char *
-get_token(
- char **string_p
-)
-{
- char *begin;
- char *newstr;
- char_ret r;
- int len;
-
- do {
- r = getachar(string_p);
- } while (r.c && isspace(r.c));
-
- if (!r.quoted && r.c == '\"') {
- begin = *string_p;
- do {
- r = getachar(string_p);
- } while (r.c && !r.quoted && r.c != '\"');
- } else {
- begin = *string_p - 1;
- do {
- r = getachar(string_p);
- } while (r.c && !r.quoted && r.c != ';' && !isspace(r.c));
- }
- len = *string_p - begin - 1;
- newstr = (char *)malloc(len + 1);
- strncpy(newstr, begin, len);
- newstr[len] = '\0';
- return newstr;
-}
-
-
-char *
-stringFromList(
- char **list,
- int *size
-)
-{
- char *begin = *list, *end;
- char *newstr;
- int newsize = *size;
-
- while (*begin && newsize && isspace(*begin)) {
- begin++;
- newsize--;
- }
- end = begin;
- while (*end && newsize && !isspace(*end)) {
- end++;
- newsize--;
- }
- if (begin == end)
- return 0;
- newstr = malloc(end - begin + 1);
- strncpy(newstr, begin, end - begin);
- *list = end;
- *size = newsize;
- return newstr;
-}
-
-char *
-valueForStringTableKey(
- char *table,
- char *key
-)
-{
- char *token;
- enum {
- KEY,
- EQUALS,
- VALUE,
- SEMICOLON,
- BEGINCOMMENT,
- ENDCOMMENT
- } state;
- BOOL foundKey;
- int len;
-
- state = KEY;
- foundKey = NO;
- while (*table) {
- token = get_token(&table);
- switch(state) {
- case KEY:
- if (strcmp(token, key) == 0)
- foundKey = YES;
- if (strncmp(token, "/*", 2) == 0)
- state = ENDCOMMENT;
- else
- state = EQUALS;
- break;
- case EQUALS:
- if (strcmp(token, "=") == 0) {
- state = VALUE;
- }
- break;
- case VALUE:
- if (foundKey) {
- return token;
- }
- state = SEMICOLON;
- break;
- case SEMICOLON:
- if (strcmp(token, ";") == 0) {
- state = KEY;
- }
- break;
- case ENDCOMMENT:
- len = strlen(token);
- if (len >= 2 && strncmp(token + len - 2, "*/", 2) == 0)
- state = KEY;
- break;
- }
- free(token);
- }
- return 0;
-}
-
-char *
-valueForBootKey(
- char *line,
- char *match
-)
-{
- char *token;
- enum {
- KEY,
- EQUALS,
- VALUE,
- WHITESPACE
- } state;
- BOOL foundKey;
- int len;
-
- state = KEY;
- while (*line) {
- token = get_token(&line);
- }
-}
-
-BOOL
-boolForKey(
- char *key
-)
-{
- char *str = valueForKey(key);
- BOOL ret;
-
- if (str && (str[0] == 'Y' || str[1] == 'y'))
- ret = YES;
- else
- ret = NO;
- free(str);
- return ret;
-}
-
-BOOL
-getIntForKey(
- char *key,
- int *value
-)
-{
- char *str = valueForKey(key), *ptr = str;
- int sum;
- BOOL ret;
-
- if (str) {
- for (sum = 0; size > 0; size--) {
- sum = (sum * 10) + (*ptr++ - '0');
- }
- *value = sum;
- ret = YES;
- } else {
- ret = NO;
- }
- free(str);
- return ret;
-}
-
-char *
-valueForKey(
- char *key
-)
-{
- char *str = valueForBootKey(kernBootStruct->bootString, key);;
-
- if (str)
- return str;
- else
- return valueForStringTableKey(kernBootStruct->config, key);
-}
-
-#define LOCALIZABLE_PATH \
- "%s/%s.config/%s.lproj/%s.strings"
-char *
-loadLocalizableStrings(
- char *name,
- char *tableName
-)
-{
- char buf[256], *config;
- register int i, count, fd = -1;
- char * paths[] = {
- ARCH_DEVICES,
- USR_DEVICES,
- "/",
- NULL
- }, **path;
-
- for (i=0; i<2; i++) {
- for (path = paths; *path; path++) {
- sprintf(buf, LOCALIZABLE_PATH, *path, name,
- (i == 0) ? Language : "English", tableName);
- if ((fd = open(buf, 0)) >= 0) {
- i = 2;
- break;
- }
- }
- }
- if (fd < 0)
- return 0;
- count = file_size(fd);
- config = malloc(count);
- count = read(fd, config, count);
- close(fd);
- if (count <= 0) {
- free(config);
- return 0;
- }
- return config;
-}
-
-char *
-bundleLongName(
- char *bundleName,
- char *tableName
-)
-{
- char *table, *name, *val;
- int size;
-
- table = loadLocalizableStrings(bundleName,
- tableName ? tableName : "Localizable");
- if ( table != 0 &&
- getValueForStringTableKey(table,"Long Name", &val, &size) == YES) {
- name = malloc(size+1);
- strncpy(name, val, size);
- free(table);
- } else {
- name = newString(bundleName);
- }
- return name;
-}
-
-int sysConfigValid;
-
-void
-addConfig(
- char *config
-)
-{
- char *configPtr = kernBootStruct->configEnd;
- int len = strlen(config);
-
- if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
- error("No room in memory for config files\n");
- return;
- }
- strcpy(configPtr, config);
- configPtr += (len + 1);
- *configPtr = 0;
- kernBootStruct->configEnd = configPtr;
-}
-
-/*
- * Returns 0 if file loaded OK,
- * -1 if file was not loaded
- * Does not print error messages.
- * Returns pointer to table in memory in *table.
- */
-int
-loadConfigFile( char *configFile, char **table, BOOL allocTable)
-{
- char *configPtr = kernBootStruct->configEnd;
- int fd, count;
-
- /* Read config file into memory */
- if ((fd = open(configFile, 0)) >= 0)
- {
- if (allocTable) {
- configPtr = malloc(file_size(fd)+2);
- } else {
- if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
- error("No room in memory for config files\n");
- close(fd);
- return -1;
- }
- verbose("Reading configuration file '%s'.\n",configFile);
- }
- if (table) *table = configPtr;
- count = read(fd, configPtr, IO_CONFIG_DATA_SIZE);
- close(fd);
-
- configPtr += count;
- *configPtr++ = 0;
- *configPtr = 0;
- if (!allocTable)
- kernBootStruct->configEnd = configPtr;
-
- return 0;
- } else {
- return -1;
- }
-}
-
-/* Returns 0 if requested config files were loaded,
- * 1 if default files were loaded,
- * -1 if no files were loaded.
- * Prints error message if files cannot be loaded.
- */
-
-int
-loadConfigDir(
- char *bundleName, // bundle directory name (e.g. "System")
- BOOL useDefault, // use Default.table instead of instance tables
- char **table, // returns pointer to config table
- BOOL allocTable // malloc the table and return in *table
-)
-{
- char *buf;
- int i, ret;
- BOOL archConfig = dirExists(ARCH_DEVICES);
-
- buf = malloc(256);
- ret = 0;
-
- // load up to 99 instance tables
- for (i=0; i < 99; i++) {
- sprintf(buf, "%s/%s.config/Instance%d.table",
- archConfig ? ARCH_DEVICES : USR_DEVICES,
- bundleName, i);
- if (useDefault || (loadConfigFile(buf, table, allocTable) != 0)) {
- if (i == 0) {
- // couldn't load first instance table;
- // try the default table
- sprintf(buf, "%s/%s.config/%s",
- archConfig ? ARCH_DEVICES : USR_DEVICES,
- bundleName,
- IO_DEFAULT_TABLE_FILENAME);
- if (loadConfigFile(buf, table, allocTable) == 0) {
- ret = 1;
- } else {
- if (!allocTable)
- error("Config file \"%s\" not found\n", buf);
- ret = -1;
- }
- }
- // we must be done.
- break;
- }
- }
- free(buf);
- return ret;
-}
-
-
-#define USR_SYSTEM_CONFIG \
- USR_DEVICES "/System.config"
-#define USR_SYSTEM_DEFAULT_FILE \
- USR_SYSTEM_CONFIG "/Default.table"
-#define ARCH_SYSTEM_CONFIG \
- ARCH_DEVICES "/System.config"
-#define ARCH_SYSTEM_DEFAULT_FILE \
- ARCH_SYSTEM_CONFIG "/Default.table"
-#define SYSTEM_CONFIG "System"
-#define LP '('
-#define RP ')'
-
-/* Returns 0 if requested config files were loaded,
- * 1 if default files were loaded,
- * -1 if no files were loaded.
- * Prints error message if files cannot be loaded.
- */
-int
-loadSystemConfig(
- char *which,
- int size
-)
-{
- char *buf, *bp, *cp;
- int ret, len, doDefault=0;
- BOOL archConfig = dirExists(ARCH_DEVICES);
-
- buf = bp = malloc(256);
- if (which && size)
- {
- for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ;
- if (*cp == LP) {
- while (len-- && *cp && *cp++ != RP) ;
- /* cp now points past device */
- strncpy(buf,which,cp - which);
- bp += cp - which;
- } else {
- cp = which;
- len = size;
- }
- if (*cp != '/') {
- strcpy(bp, archConfig ?
- ARCH_SYSTEM_CONFIG : USR_SYSTEM_CONFIG);
- strcat(bp, "/");
- strncat(bp, cp, len);
- if (strncmp(cp + len - strlen(IO_TABLE_EXTENSION),
- IO_TABLE_EXTENSION, strlen(IO_TABLE_EXTENSION)) != 0)
- strcat(bp, IO_TABLE_EXTENSION);
- } else {
- strncpy(bp, cp, len);
- bp[size] = '\0';
- }
- if ((strcmp(bp, USR_SYSTEM_DEFAULT_FILE) == 0) ||
- (strcmp(bp, ARCH_SYSTEM_DEFAULT_FILE) == 0))
- doDefault = 1;
- ret = loadConfigFile(bp = buf, 0, 0);
- } else {
- ret = loadConfigDir((bp = SYSTEM_CONFIG), 0, 0, 0);
- }
- if (ret < 0) {
- error("System config file '%s' not found\n", bp);
- } else
- sysConfigValid = 1;
- free(buf);
- return (ret < 0 ? ret : doDefault);
-}
-
-
-int
-loadOtherConfigs(
- int useDefault
-)
-{
- char *val, *table;
- int count;
- char *string;
- int fd, ret;
-
- if (getValueForKey( "Boot Drivers", &val, &count))
- {
- while (string = stringFromList(&val, &count)) {
- ret = loadConfigDir(string, useDefault, &table, 0);
- if (ret >= 0) {
- if ((fd = openDriverReloc(string)) >= 0) {
- verbose("Loading binary for %s device driver.\n",string);
- if (loadDriver(string, fd) < 0)
- error("Error loading %s device driver.\n",string);
- close(fd);
- }
- driverWasLoaded(string, table, NULL);
- free(string);
- } else {
- driverIsMissing(string);
- }
- }
- } else {
- error("Warning: No active drivers specified in system config.\n");
- }
-
- kernBootStruct->first_addr0 =
- (int)kernBootStruct->configEnd + 1024;
- return 0;
-}
-
-static BOOL
-dirExists(char *path)
-{
- int fd;
-
- if ((fd = open(path, 0)) < 0) {
- return NO;
- } else {
- close(fd);
- return YES;
- }
-}
-
-
-
* Created
*/
-#include <mach/mach_types.h>
-// #include "legacy/KernDevice.h"
-#include "legacy/PCI.h"
-
-#include "kernBootStruct.h"
#include "libsaio.h"
-#include "io_inline.h"
#include "pci.h"
static BOOL testMethod1(void);
PCI_bus_info_t *info /* pass in the PCI boot info struct */
)
{
-
unsigned int maxBusNum = 0, maxDevNum = 0, useMethod = 0;
_pci_bus_method_t method = NULL;
_pci_slot_info_t *slot_array;
}
}
-
if (useMethod == 1)
method = getMethod1;
else if (useMethod == 2)
method = getMethod2;
else
return NULL;
-
+
nslots = scanBus(maxBusNum, maxDevNum, method, NULL);
slot_array = (_pci_slot_info_t *)
malloc(sizeof(_pci_slot_info_t) * nslots +1);
extern _pci_slot_info_t *PCISlotInfo;
+/* The IOPCIConfigSpace structure can be used to decode the 256 byte
+ * configuration space presented by each PCI device. This structure
+ * is based on the PCI LOCAL BUS SPECIFICATION, rev 2.1, section 6.1
+ */
+
+typedef struct _IOPCIConfigSpace {
+ unsigned short VendorID;
+ unsigned short DeviceID;
+ unsigned short Command;
+ unsigned short Status;
+ unsigned long RevisionID:8;
+ unsigned long ClassCode:24;
+ unsigned char CacheLineSize;
+ unsigned char LatencyTimer;
+ unsigned char HeaderType;
+ unsigned char BuiltInSelfTest;
+ unsigned long BaseAddress[6];
+ unsigned long CardbusCISpointer;
+ unsigned short SubVendorID;
+ unsigned short SubDeviceID;
+ unsigned long ROMBaseAddress;
+ unsigned long reserved3;
+ unsigned long reserved4;
+ unsigned char InterruptLine;
+ unsigned char InterruptPin;
+ unsigned char MinGrant;
+ unsigned char MaxLatency;
+ unsigned long VendorUnique[48];
+} IOPCIConfigSpace;
+
+
+/* PCI_DEFAULT_DATA is the value resulting from a read to a non-existent
+ * PCI device's configuration space.
+ */
+
+#define PCI_DEFAULT_DATA 0xffffffff
+
+
+/* PCI_INVALID_VENDOR_ID is a Vendor ID reserved by the PCI/SIG and is
+ * guaranteed not to be assigned to any vendor.
+ */
+
+#define PCI_INVALID_VENDOR_ID 0xffff
+
#endif /* !__LIBSAIO_PCI_H */
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1990 Carnegie-Mellon University
- * Copyright (c) 1989 Carnegie-Mellon University
- * Copyright (c) 1988 Carnegie-Mellon University
- * All rights reserved. The CMU software License Agreement specifies
- * the terms and conditions for use and redistribution.
- *
- */
-/*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- *
- * @(#)saio.h 7.1 (Berkeley) 6/5/86
- */
-
-#ifndef __LIBSAIO_SAIO_H
-#define __LIBSAIO_SAIO_H
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/vnode.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-
-/*
- * Io block: includes an inode, cells for the use of seek, etc,
- * and a buffer.
- */
-struct iob {
- int i_flgs; /* see F_ below */
- struct inode i_ino; /* inode, if file */
- daddr_t i_boff; /* block offset on device */
- unsigned int i_offset; /* seek offset in file */
- daddr_t i_bn; /* 1st block # of next read */
- char * i_ma; /* memory address of i/o buffer */
- int i_cc; /* character count of transfer */
- int i_error; /* error # return */
- char * i_buf; /* i/o buffer */
- struct fs * i_ffs; /* file system super block info */
- int biosdev; /* bios device for file, i_ino inadequate */
- daddr_t dirbuf_blkno; /* blk of currently buffered dir */
- int partition; /* which partition */
-};
-
-struct dirstuff {
- int loc;
- struct iob * io;
-};
-
-#define F_READ 0x1 /* file opened for reading */
-#define F_WRITE 0x2 /* file opened for writing */
-#define F_ALLOC 0x4 /* buffer allocated */
-#define F_FILE 0x8 /* file instead of device */
-#define F_NBSF 0x10 /* no bad sector forwarding */
-#define F_SSI 0x40 /* set skip sector inhibit */
-#define F_MEM 0x80 /* memory instead of file or device */
-
-/* IO types */
-#define F_RDDATA 0x0100 /* read data */
-#define F_WRDATA 0x0200 /* write data */
-#define F_HDR 0x0400 /* include header on next i/o */
-
-#define F_TYPEMASK 0xff00
-
-extern char * devsw[];
-
-/*
- * Request codes. Must be the same a F_XXX above
- */
-#define READ 1
-#define WRITE 2
-
-#define NBUFS 4
-extern char * b[NBUFS];
-extern daddr_t blknos[NBUFS];
-
-#define NFILES 6
-extern struct iob iob[NFILES];
-
-/* Error codes */
-#define EBADF 1 /* bad file descriptor */
-#define EOFFSET 2 /* relative seek not supported */
-#define EDEV 3 /* improper device specification on open */
-#define ENXIO 4 /* unknown device specified */
-#define ESRCH 6 /* directory search for file failed */
-#define EIO 7 /* generic error */
-#define ECMD 10 /* undefined driver command */
-#define EBSE 11 /* bad sector error */
-#define EWCK 12 /* write check error */
-#define EECC 13 /* uncorrectable ecc error */
-#define EHER 14 /* hard error */
-
-#define BIOS_DEV_FLOPPY 0x0
-#define BIOS_DEV_HD 0x80
-#define BIOS_DEV_WIN BIOS_DEV_HD
-#define BIOS_DEV_EN 0xff /* not really a BIOS device number */
-
-#define DEV_SD 0
-#define DEV_HD 1
-#define DEV_FLOPPY 2
-#define DEV_EN 3
-
-#define BIOSDEV(dev) ((dev) == DEV_FLOPPY ? BIOS_DEV_FLOPPY : BIOS_DEV_WIN)
-
-#define NSECS 16 /* number of buffered 512 byte sectors */
-
-#define Dev(x) (((x)>>B_TYPESHIFT)&B_TYPEMASK)
-
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#endif /* !__LIBSAIO_SAIO_H */
#include "saio_types.h"
/* asm.s */
-extern void real_to_prot(void);
-extern void prot_to_real(void);
-extern void halt(void);
-extern void startprog(unsigned int address);
+extern void real_to_prot(void);
+extern void prot_to_real(void);
+extern void halt(void);
+extern void startprog(unsigned int address);
+extern void loader(UInt32 code, UInt32 cmdptr);
/* bios.s */
-extern void bios(biosBuf_t *bb);
-extern void get_memsize(biosBuf_t *bb);
+extern void bios(biosBuf_t *bb);
+extern void get_memsize(biosBuf_t *bb);
/* biosfn.c */
#ifdef EISA_SUPPORT
-extern BOOL eisa_present(void);
+extern BOOL eisa_present(void);
#endif
-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 void putc(int ch);
-extern int getc(void);
-extern int readKeyboardStatus(void);
-extern unsigned int time18(void);
-extern unsigned int get_diskinfo(int dev);
-extern int APMPresent(void);
-extern int APMConnect32(void);
-extern int memsize(int i);
-extern void video_mode(int mode);
-extern void setCursorPosition(int x, int y);
+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 void putc(int ch);
+extern void putca(int ch, int attr, int repeat);
+extern int getc(void);
+extern int readKeyboardStatus(void);
+extern unsigned int time18(void);
+extern unsigned int get_diskinfo(int dev);
+extern int APMPresent(void);
+extern int APMConnect32(void);
+extern int memsize(int i);
+extern void video_mode(int mode);
+extern void setCursorPosition(int x, int y, int page);
+extern void setCursorType(int type);
+extern void getCursorPositionAndType(int *x, int *y, int *type);
+extern void scollPage(int x1, int y1, int x2, int y2, int attr, int rows, int dir);
+extern void clearScreenRows(int y1, int y2);
+extern void setActiveDisplayPage( int page );
/* bootstruct.c */
-extern void initKernBootStruct(void);
+extern void initKernBootStruct(int biosdev);
+
+/* cache.c */
+extern void CacheInit(CICell ih, long blockSize);
+extern long CacheRead(CICell ih, char *buffer, long long offset,
+ long length, long cache);
/* console.c */
-extern BOOL gVerboseMode;
-extern void putchar(int ch);
-extern int getchar(void);
-extern int printf(const char *format, ...);
-extern int error(const char *format, ...);
-extern int verbose(const char *format, ...);
+extern BOOL gVerboseMode;
+extern BOOL gErrors;
+extern void putchar(int ch);
+extern int getchar(void);
+extern int printf(const char *format, ...);
+extern int error(const char *format, ...);
+extern int verbose(const char *format, ...);
/* disk.c */
-extern void devopen(char *name, struct iob *io);
-extern int devread(struct iob *io);
-extern void devflush(void);
-
-/* gets.c */
-extern int gets(char *buf, int len);
-extern int Gets(
- char *buf,
- int len,
- int timeout,
- char *prompt,
- char *message
-);
+extern BVRef diskScanBootVolumes(int biosdev, int *count);
+extern void diskSeek(BVRef bvr, long long position);
+extern int diskRead(BVRef bvr, long addr, long length);
+extern int readBootSector(int biosdev, unsigned int secno, void *buffer);
/* load.c */
-extern int openfile(char *filename, int ignored);
-
-extern int loadmacho(
- struct mach_header *head,
- int dev,
- int io,
- entry_t *entry,
- char **addr,
- int *size,
- int file_offset
-);
-extern int loadprog(
- int dev,
- int fd,
- struct mach_header *headOut,
- entry_t *entry,
- char **addr,
- int *size
-);
+extern int openfile(const char *filename, int ignored);
+extern int loadprog(int dev, int fd, struct mach_header *headOut,
+ entry_t *entry, char **addr, int *size);
/* misc.c */
-extern void sleep(int n);
-extern void enableA20(void);
-extern void turnOffFloppy(void);
-extern char *newString(char *oldString);
+extern void sleep(int n);
+extern void enableA20(void);
+extern void turnOffFloppy(void);
+extern char * newString(const char *oldString);
+extern void stop(const char *message);
+
+/* nbp.c */
+extern UInt32 nbpUnloadBaseCode();
+extern BVRef nbpScanBootVolumes(int biosdev, int *count);
/* stringTable.c */
extern char * newStringFromList(char **list, int *size);
-extern int stringLength(char *table, int compress);
-extern BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size);
+extern int stringLength(const char *table, int compress);
+extern BOOL getValueForStringTableKey(const char *table, const char *key, const char **val, int *size);
extern BOOL removeKeyFromTable(const char *key, char *table);
extern char * newStringForStringTableKey(char *table, char *key);
extern char * newStringForKey(char *key);
-extern BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len);
-extern BOOL getValueForKey(char *key, char **val, int *size);
-extern BOOL getBoolForKey(char *key);
-extern BOOL getIntForKey(char *key, int *val);
+extern BOOL getValueForBootKey(const char *line, const char *match, const char **matchval, int *len);
+extern BOOL getValueForKey(const char *key, const char **val, int *size);
+extern BOOL getBoolForKey(const char *key);
+extern BOOL getIntForKey(const char *key, int *val);
#if 0
extern char * loadLocalizableStrings(char *name, char *tableName);
extern char * bundleLongName(char *bundleName, char *tableName);
extern int loadOtherConfigs(int useDefault);
#endif
-extern int loadConfigFile( char *configFile, char **table, BOOL allocTable);
-extern int loadConfigDir(char *bundleName, BOOL useDefault, char **table,
+extern int loadConfigFile(const char *configFile, const char **table, BOOL allocTable);
+extern int loadConfigDir(const char *bundleName, BOOL useDefault, const char **table,
BOOL allocTable);
-extern int loadSystemConfig(char *which, int size);
-extern void addConfig(char *config);
+extern int loadSystemConfig(const char *which, int size);
+extern void addConfig(const char *config);
/* sys.c */
-extern void stop(char *message);
-extern int openmem(char * buf, int len);
-extern int open(char *str, int how);
-extern int close(int fdesc);
-extern int file_size(int fdesc);
-extern int read(int fdesc, char *buf, int count);
-extern int b_lseek(int fdesc, unsigned int addr, int ptr);
-extern int tell(int fdesc);
-extern void flushdev(void);
-extern char *usrDevices(void);
-extern struct dirstuff * opendir(char *path);
-extern int closedir(struct dirstuff *dirp);
-extern struct direct * readdir(struct dirstuff *dirp);
-extern int currentdev(void);
-extern int switchdev(int dev);
-
-/* ufs_byteorder.c */
-extern void byte_swap_superblock(struct fs *sb);
-extern void byte_swap_inode_in(struct dinode *dc, struct dinode *ic);
-extern void byte_swap_dir_block_in(char *addr, int count);
-
-/*
- * vbe.c
- */
-extern int set_linear_video_mode(unsigned short mode);
-
-/*
- * vga.c
- */
-extern void set_video_mode(unsigned int mode);
+extern long LoadFile(const char *fileSpec);
+extern long GetDirEntry(const char *dirSpec, long *dirIndex, const char **name,
+ long *flags, long *time);
+extern long GetFileInfo(const char *dirSpec, const char *name,
+ long *flags, long *time);
+extern int openmem(char *buf, int len);
+extern int open(const char *str, int how);
+extern int close(int fdesc);
+extern int file_size(int fdesc);
+extern int read(int fdesc, char *buf, int count);
+extern int b_lseek(int fdesc, int addr, int ptr);
+extern int tell(int fdesc);
+extern const char * usrDevices(void);
+extern struct dirstuff * opendir(const char *path);
+extern int closedir(struct dirstuff *dirp);
+extern int readdir(struct dirstuff *dirp, const char **name, long *flags, long *time);
+extern void flushdev(void);
+extern int currentdev(void);
+extern int switchdev(int dev);
+extern BVRef scanBootVolumes(int biosdev, int *count);
+extern BVRef selectBootVolume(BVRef chain);
+extern void getBootVolumeDescription(BVRef bvr, char *str, long strMaxLen);
#endif /* !__LIBSAIO_SAIO_INTERNAL_H */
#ifndef __LIBSAIO_SAIO_TYPES_H
#define __LIBSAIO_SAIO_TYPES_H
-typedef char BOOL;
-#define NO 0
-#define YES 1
-
-#include <mach-o/loader.h>
-#undef i386_THREAD_STATE
-#undef i386_THREAD_STATE_COUNT
-#include <mach/i386/thread_status.h>
#include <sys/reboot.h>
+#include <sys/types.h>
+#include "bios.h"
+#include "nbp_cmd.h"
-typedef unsigned long entry_t;
+#if 0
+#define DEBUG_DISK(x) printf x
+#else
+#define DEBUG_DISK(x)
+#endif
-#include <stdarg.h>
-#include "bios.h"
-#include "saio.h"
+typedef char BOOL;
+#define NO 0
+#define YES 1
+
+typedef unsigned long entry_t;
typedef struct {
unsigned int sectors:8;
int totalDrives;
};
+struct BootVolume;
+typedef struct BootVolume * BVRef;
+typedef struct BootVolume * CICell;
+
+typedef long (*FSInit)(CICell ih);
+typedef long (*FSLoadFile)(CICell ih, char * filePath);
+typedef long (*FSGetDirEntry)(CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time);
+typedef void (*BVGetDescription)(CICell ih, char * str, long strMaxLen);
+
+struct iob {
+ unsigned int i_flgs; /* see F_* below */
+ unsigned int i_offset; /* seek byte offset in file */
+ int i_filesize; /* size of file */
+ char * i_buf; /* file load address */
+};
+
+#define F_READ 0x1 /* file opened for reading */
+#define F_WRITE 0x2 /* file opened for writing */
+#define F_ALLOC 0x4 /* buffer allocated */
+#define F_FILE 0x8 /* file instead of device */
+#define F_NBSF 0x10 /* no bad sector forwarding */
+#define F_SSI 0x40 /* set skip sector inhibit */
+#define F_MEM 0x80 /* memory instead of file or device */
+
+struct dirstuff {
+ char * dir_path; /* directory path */
+ long dir_index; /* directory entry index */
+ BVRef dir_bvr; /* volume reference */
+};
+
+struct BootVolume {
+ BVRef next; /* list linkage pointer */
+ int biosdev; /* BIOS device number */
+ unsigned int flags; /* attribute flags */
+ BVGetDescription description; /* BVGetDescription function */
+ int part_no; /* partition number (1 based) */
+ unsigned int part_boff; /* partition block offset */
+ unsigned int part_type; /* partition type */
+ unsigned int fs_boff; /* 1st block # of next read */
+ FSLoadFile fs_loadfile; /* FSLoadFile function */
+ FSGetDirEntry fs_getdirentry; /* FSGetDirEntry function */
+};
+
+enum {
+ kBVFlagPrimary = 0x01,
+ kBVFlagNativeBoot = 0x02,
+ kBVFlagForeignBoot = 0x04
+};
+
+enum {
+ kBIOSDevTypeFloppy = 0x00,
+ kBIOSDevTypeHardDrive = 0x80,
+ kBIOSDevTypeNetwork = 0xE0,
+ kBIOSDevUnitMask = 0x0F,
+ kBIOSDevTypeMask = 0xF0,
+ kBIOSDevMask = 0xFF
+};
+
+#define BIOS_DEV_TYPE(d) ((d) & kBIOSDevTypeMask)
+#define BIOS_DEV_UNIT(d) ((d) & kBIOSDevUnitMask)
+
+/*
+ * KernBootStruct device types.
+ */
+enum {
+ DEV_SD = 0,
+ DEV_HD = 1,
+ DEV_FD = 2,
+ DEV_EN = 3
+};
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define MAKEKERNDEV(t, u, p) MAKEBOOTDEV(t, 0, 0, u, p)
+
#endif /* !__LIBSAIO_SAIO_TYPES_H */
--- /dev/null
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License"). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LIBSAIO_SL_H
+#define __LIBSAIO_SL_H
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/vnode.h>
+#include "libsaio.h"
+
+#define SWAP_BE16(x) NXSwapBigShortToHost(x)
+#define SWAP_BE32(x) NXSwapBigLongToHost(x)
+#define SWAP_BE64(x) NXSwapBigLongLongToHost(x)
+
+// File Permissions and Types
+enum {
+ kPermOtherExecute = 1 << 0,
+ kPermOtherWrite = 1 << 1,
+ kPermOtherRead = 1 << 2,
+ kPermGroupExecute = 1 << 3,
+ kPermGroupWrite = 1 << 4,
+ kPermGroupRead = 1 << 5,
+ kPermOwnerExecute = 1 << 6,
+ kPermOwnerWrite = 1 << 7,
+ kPermOwnerRead = 1 << 8,
+ kPermMask = 0x1FF,
+ kOwnerNotRoot = 1 << 9,
+ kFileTypeUnknown = 0x0 << 16,
+ kFileTypeFlat = 0x1 << 16,
+ kFileTypeDirectory = 0x2 << 16,
+ kFileTypeLink = 0x3 << 16,
+ kFileTypeMask = 0x3 << 16
+};
+
+#define Seek(c, p) diskSeek(c, p);
+#define Read(c, a, l) diskRead(c, a, l);
+
+extern void * gFSLoadAddress;
+
+#endif /* !__LIBSAIO_SL_H */
*/
#include "libsaio.h"
-#include "kernBootStruct.h"
#include "stringConstants.h"
#include "legacy/configTablePrivate.h"
extern char *Language;
extern char *LoadableFamilies;
-static void eatThru(char val, char **table_p);
+static void eatThru(char val, const char **table_p);
static inline int isspace(char c)
{
* Compare a string to a key with quoted characters
*/
static inline int
-keyncmp(char *str, char *key, int n)
+keyncmp(const char *str, const char *key, int n)
{
int c;
while (n--) {
return 0;
}
-static void eatThru(char val, char **table_p)
+static void eatThru(char val, const char **table_p)
{
- register char *table = *table_p;
+ register const char *table = *table_p;
register BOOL found = NO;
while (*table && !found)
/*
* compress == compress escaped characters to one character
*/
-int stringLength(char *table, int compress)
+int stringLength(const char *table, int compress)
{
int ret = 0;
// looks in table for strings of format << "key" = "value"; >>
// or << "key"; >>
-BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size)
+BOOL getValueForStringTableKey(const char *table, const char *key, const char **val, int *size)
{
int keyLength;
- char *tableKey;
+ const char *tableKey;
do
{
char *key
)
{
- char *val, *newstr, *p;
+ const char *val;
+ char *newstr, *p;
int size;
if (getValueForStringTableKey(table, key, &val, &size)) {
- newstr = malloc(size+1);
+ newstr = (char *)malloc(size+1);
for (p = newstr; size; size--, p++, val++) {
if ((*p = *val) == '\\') {
switch (*++val) {
char *
newStringForKey(char *key)
{
- char *val, *newstr;
+ const char *val;
+ char *newstr;
int size;
if (getValueForKey(key, &val, &size) && size) {
- newstr = malloc(size + 1);
+ newstr = (char *)malloc(size + 1);
strncpy(newstr, val, size);
return newstr;
} else {
* non-whitespace characters, or enclosed in quotes.
*/
-static char *getToken(char *line, char **begin, int *len)
+static const char *getToken(const char *line, const char **begin, int *len)
{
if (*line == '\"') {
*begin = ++line;
return line;
}
-BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len)
+BOOL getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
{
- char *key, *value;
+ const char *key, *value;
int key_len, value_len;
while (*line) {
}
BOOL getBoolForKey(
- char *key
+ const char *key
)
{
- char *val;
+ const char *val;
int size;
if (getValueForKey(key, &val, &size) && (size >= 1) &&
}
BOOL getIntForKey(
- char *key,
+ const char *key,
int *value
)
{
- char *val;
+ const char *val;
int size, sum;
if (getValueForKey(key, &val, &size)) {
}
BOOL getValueForKey(
- char *key,
- char **val,
+ const char *key,
+ const char **val,
int *size
)
{
{
char buf[256], *config;
register int count, fd = -1;
- char *device_dir = usrDevices();
+ const char *device_dir = usrDevices();
sprintf(buf, LOCALIZABLE_PATH, device_dir, name,
Language, tableName);
void
addConfig(
- char *config
+ const char *config
)
{
char *configPtr = kernBootStruct->configEnd;
* Allocates an extra number of bytes for table expansion.
*/
int
-loadConfigFile( char *configFile, char **table, BOOL allocTable)
+loadConfigFile(const char *configFile, const char **table, BOOL allocTable)
{
char *configPtr = kernBootStruct->configEnd;
int fd, count;
int
loadConfigDir(
- char *bundleName, // bundle directory name (e.g. "System")
+ const char *bundleName, // bundle directory name (e.g. "System")
BOOL useDefault, // use Default.table instead of instance tables
- char **table, // returns pointer to config table
+ const char **table, // returns pointer to config table
BOOL allocTable // malloc the table and return in *table
)
{
char *buf;
int i, max, ret;
- char *device_dir = usrDevices();
+ const char *device_dir = usrDevices();
buf = malloc(256);
ret = 0;
*/
int
loadSystemConfig(
- char *which,
+ const char *which,
int size
)
{
- char *buf, *bp, *cp;
+ char *buf, *bp;
+ const char *cp;
int ret, len, doDefault=0;
- char *device_dir = usrDevices();
+ const char *device_dir = usrDevices();
#if 0
printf("In Load system config which=%d ; size=%d\n", which, size);
* @(#)sys.c 7.1 (Berkeley) 6/5/86
*/
-#include <sys/param.h>
-#include <ufs/ufs/dir.h>
-#include <sys/reboot.h>
-#include <architecture/byte_order.h>
-#include "ufs_byteorder.h"
#include "libsaio.h"
-#include "cache.h"
-#include "kernBootStruct.h"
-#include "stringConstants.h"
-#include <ufs/ffs/fs.h>
-#include "nbp.h"
-#include "memory.h"
-
-char * gFilename;
-
-extern int ram_debug_sarld; // in load.c
-
-#define DCACHE 1
-#define ICACHE 1
-#define SYS_MESSAGES 1
-#define CHECK_CAREFULLY 0
-#define COMPRESSION 1
-
-// #define DEBUG 1
-
-#ifdef DEBUG
-#define DPRINT(x) { printf x; }
-#define DSPRINT(x) { printf x; sleep(2); }
-#define RDPRINT(x) { if (ram_debug_sarld) printf x; }
-#define RDSPRINT(x) { if (ram_debug_sarld) printf x; sleep(2); }
-#else
-#define DPRINT(x)
-#define DSPRINT(x)
-#define RDPRINT(x)
-#define RDSPRINT(x)
-#endif
-
-char * devsw[] = {
- "sd",
- "hd",
- "fd",
- "en",
- NULL
+
+struct devsw {
+ const char * name;
+ unsigned char biosdev;
};
-//#############################################################################
-//#
-//# Disk filesystem functions.
-//#
-//#############################################################################
+static struct devsw devsw[] =
+{
+ { "sd", 0x80 }, /* DEV_SD */
+ { "hd", 0x80 }, /* DEV_HD */
+ { "fd", 0x00 }, /* DEV_FD */
+ { "en", 0xE0 }, /* DEV_EN */
+ { 0, 0 }
+};
-static ino_t dlook(char *s, struct iob *io);
-static char * xx(char *str, struct iob *file);
-static int ffs(register long mask);
+/*
+ * Max number of file descriptors.
+ */
+#define NFILES 6
-extern int label_secsize;
+static struct iob iob[NFILES];
-#define BIG_ENDIAN_INTEL_FS __LITTLE_ENDIAN__
+void * gFSLoadAddress = 0;
-#if ICACHE
-#define ICACHE_SIZE 256
-#define ICACHE_READAHEAD 8 // read behind and read ahead
-static cache_t * icache;
-#endif ICACHE
+static BVRef getBootVolumeRef( const char * path, const char ** outPath );
+static BVRef newBootVolumeRef( int biosdev, int partno );
-#if DCACHE
-#define DCACHE_SIZE 16 // 1k (DIRBLKSIZ) blocks
-static cache_t * dcache;
-#endif
+//==========================================================================
+// LoadFile - LOW-LEVEL FILESYSTEM FUNCTION.
+// Load the specified file to the load buffer at LOAD_ADDR.
-#define DEV_BSIZE label_secsize
+long LoadFile(const char * fileSpec)
+{
+ const char * filePath;
+ long fileSize;
+ BVRef bvr;
-#if CHECK_CAREFULLY
-static int open_init;
-#endif
+ // Resolve the boot volume from the file spec.
-static struct fs * fs_block;
-static int fs_block_valid;
+ if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL)
+ return -1;
-#define SUPERBLOCK_ERROR "Bad superblock: error %d\n"
+ // Read file into load buffer. The data in the load buffer will be
+ // overwritten by the next LoadFile() call.
-/*==========================================================================
- *
- *
- */
-static struct iob * iob_from_fdesc(int fdesc)
-{
- register struct iob * file;
-
- if (fdesc < 0 || fdesc >= NFILES ||
- ((file = &iob[fdesc])->i_flgs & F_ALLOC) == 0)
- return NULL;
- else
- return file;
-}
+ gFSLoadAddress = (void *) LOAD_ADDR;
+ fileSize = bvr->fs_loadfile(bvr, (char *)filePath);
-/***************************************************************************
- *
- * Disk functions.
- *
- ***************************************************************************/
+ // Return the size of the file, or -1 if load failed.
-/*==========================================================================
- *
- *
- */
-static int
-openi(int n, struct iob * io)
-{
- struct dinode * dp;
- int cc, i, j, n_round;
-
-#if ICACHE
- struct dinode *ip;
-
- if (icache == 0) {
- icache = cacheInit(ICACHE_SIZE, sizeof(struct dinode));
- }
-#endif /* ICACHE */
-
- io->i_offset = 0;
- io->i_bn = fsbtodb(io->i_ffs, ino_to_fsba(io->i_ffs, n)) + io->i_boff;
- io->i_cc = io->i_ffs->fs_bsize;
- io->i_ma = io->i_buf;
-
-#if ICACHE
- if (cacheFind(icache, n, 0, (char **)&ip) == 1) {
- io->i_ino.i_din = *ip;
- cc = 0;
- } else {
-#endif ICACHE
- cc = devread(io);
- dp = (struct dinode *)io->i_buf;
- n_round = (n / INOPB(io->i_ffs)) * INOPB(io->i_ffs);
-#if ICACHE
- /* Read multiple inodes into cache */
- for (i = max(ino_to_fsbo(io->i_ffs, n) - ICACHE_READAHEAD, 0),
- j = min(i+2*ICACHE_READAHEAD, INOPB(io->i_ffs)); i < j; i++) {
- cacheFind(icache, n_round + i, 0, (char **)&ip);
-
-#if BIG_ENDIAN_INTEL_FS
-#warning Building with Big Endian changes
- byte_swap_dinode_in(&dp[i]);
-#endif /* BIG_ENDIAN_INTEL_FS */
-
- *ip = dp[i];
- if (i == ino_to_fsbo(io->i_ffs, n)) {
- io->i_ino.i_din = *ip;
- }
- }
- }
-#else ICACHE
-
-#if BIG_ENDIAN_INTEL_FS
- byte_swap_dinode_in(&dp[ino_to_fsbo(io->i_ffs, n)]);
-#endif /* BIG_ENDIAN_INTEL_FS */
-
- io->i_ino.i_din = dp[ino_to_fsbo(io->i_ffs, n)];
-#endif ICACHE
-
- io->i_ino.i_number = n;
- return (cc);
+ return fileSize;
}
-/*==========================================================================
- *
- *
- */
-static int
-readlink(struct iob * io, char * buf, int len)
+//==========================================================================
+// GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION.
+// Fetch the next directory entry for the given directory.
+
+long GetDirEntry(const char * dirSpec, long * dirIndex, const char ** name,
+ long * flags, long * time)
{
- register struct inode * ip;
-
- ip = &io->i_ino;
-#if 1
- /* read contents */
- io->i_offset = 0;
- io->i_cc = 0;
- io->i_flgs |= F_FILE;
- if (read(io - iob, buf, len) < 0)
+ const char * dirPath;
+ BVRef bvr;
+
+ // Resolve the boot volume from the dir spec.
+
+ if ((bvr = getBootVolumeRef(dirSpec, &dirPath)) == NULL)
return -1;
-#else
- if (ip->i_icflags & IC_FASTLINK) {
- if (ip->i_size > len)
- return -1;
- bcopy(ip->i_symlink, buf, ip->i_size);
- } else {
- /* read contents */
- io->i_offset = 0;
- io->i_cc = 0;
- io->i_flgs |= F_FILE;
- if (read(io - iob, buf, len) < 0)
- return -1;
- }
-#endif
- return 0;
+
+ // Return 0 on success, or -1 if there are no additional entries.
+
+ return bvr->fs_getdirentry( bvr,
+ /* dirPath */ (char *)dirPath,
+ /* dirIndex */ dirIndex,
+ /* dirEntry */ (char **)name, flags, time );
}
-/*==========================================================================
- *
- *
- */
-static int
-find(char * path, struct iob * file)
+//==========================================================================
+// GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION.
+// Get attributes for the specified file.
+
+long GetFileInfo(const char * dirSpec, const char * name,
+ long * flags, long * time)
{
- char * q;
- char c;
- int n, parent;
- char * lbuf = malloc(MAXPATHLEN + 1);
- int ret;
-
-#if CHECK_CAREFULLY
- if (path==NULL || *path=='\0') {
- error("null path\n");
- ret = 0; goto out;
- }
-#endif CHECK_CAREFULLY
-
- DSPRINT(("in find: path=%s\n", path));
-
-root:
- n = ROOTINO;
- if (openi(n, file) < 0)
- {
- DPRINT(("openi failed\n"));
-
-#if SYS_MESSAGES
- error("bad root inode\n");
-#endif
-
- ret = 0; goto out;
- }
- DPRINT(("openi ok\n"));
-
- while (*path)
- {
- while (*path == '/')
- path++;
- q = path;
- while(*q != '/' && *q != '\0')
- q++;
- c = *q;
- *q = '\0';
- if (q == path) path = "." ; /* "/" means "/." */
-
- parent = n;
- if ((n = dlook(path, file)) != 0)
- {
- if (c == '\0')
- break;
- if (openi(n, file) < 0)
- {
- *q = c;
- ret = 0; goto out;
- }
- *q = c;
- path = q;
-
- /* Check for symlinks */
- if (file->i_ino.i_mode & IFLNK) {
- char *buf = malloc(MAXPATHLEN + 1);
- if (readlink(file, buf, MAXPATHLEN + 1) < 0)
- return -1;
- strcat(buf, q);
- strcpy(lbuf, buf);
- free(buf);
- path = lbuf;
- if (*path == '/')
- goto root;
- if (openi(parent, file) < 0) {
- ret = 0; goto out;
- }
- }
- continue;
- }
- else
- {
- *q = c;
- ret = 0; goto out;
- }
- }
- ret = n;
-out:
- free(lbuf);
- return (ret);
+ long index = 0;
+ const char * entryName;
+
+ while (GetDirEntry(dirSpec, &index, &entryName, flags, time) == 0)
+ {
+ if (strcmp(entryName, name) == 0)
+ return 0; // success
+ }
+ return -1; // file not found
}
-/*==========================================================================
- *
- *
- */
-static daddr_t
-sbmap(struct iob * io, daddr_t bn)
+//==========================================================================
+// iob_from_fdesc()
+//
+// Return a pointer to an allocated 'iob' based on the file descriptor
+// provided. Returns NULL if the file descriptor given is invalid.
+
+static struct iob * iob_from_fdesc(int fdesc)
{
- register struct inode * ip;
- int i, j, sh;
- daddr_t nb, * bap;
-
- ip = &io->i_ino;
-
- if (bn < 0) {
-#if SYS_MESSAGES
- error("bn negative\n");
-#endif
- return ((daddr_t)0);
- }
-
- /*
- * blocks 0..NDADDR are direct blocks
- */
- if (bn < NDADDR)
- {
- nb = ip->i_db[bn];
- return (nb);
- }
-
- /*
- * addresses NIADDR have single and double indirect blocks.
- * the first step is to determine how many levels of indirection.
- */
- RDPRINT(("In NINADDR\n"));
-
- sh = 1;
- bn -= NDADDR;
- for (j = NIADDR; j > 0; j--) {
- sh *= NINDIR(io->i_ffs);
- if (bn < sh)
- break;
- bn -= sh;
- }
-
- if (j == 0) {
-#if SYS_MESSAGES
- error("bn ovf %d\n", bn);
-#endif
- return ((daddr_t)0);
- }
-
- /*
- * fetch the first indirect block address from the inode
- */
- nb = ip->i_ib[NIADDR - j];
- if (nb == 0) {
-#if SYS_MESSAGES
- error("bn void %d\n",bn);
-#endif
- return ((daddr_t)0);
- }
-
- /*
- * fetch through the indirect blocks
- */
- for (; j <= NIADDR; j++) {
- if (blknos[j] != nb) {
- io->i_bn = fsbtodb(io->i_ffs, nb) + io->i_boff;
- if (b[j] == (char *)0)
- b[j] = malloc(MAXBSIZE);
- io->i_ma = b[j];
- io->i_cc = io->i_ffs->fs_bsize;
-
- RDPRINT(("Indir block read\n"));
-
- if (devread(io) != io->i_ffs->fs_bsize) {
-#if SYS_MESSAGES
- error("bn %d: read error\n", io->i_bn);
-#endif
- return ((daddr_t)0);
- }
- blknos[j] = nb;
- }
- bap = (daddr_t *)b[j];
- sh /= NINDIR(io->i_ffs);
- i = (bn / sh) % NINDIR(io->i_ffs);
-#if BIG_ENDIAN_INTEL_FS
- nb = NXSwapBigLongToHost(bap[i]);
-#else /* BIG_ENDIAN_INTEL_FS */
- nb = bap[i];
-#endif /* BIG_ENDIAN_INTEL_FS */
- if (nb == 0) {
-#if SYS_MESSAGES
- error("bn void %d\n",bn);
-#endif
- return ((daddr_t)0);
- }
- }
-
- return (nb);
+ register struct iob * io;
+
+ if (fdesc < 0 || fdesc >= NFILES ||
+ ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0)
+ return NULL;
+ else
+ return io;
}
-/*==========================================================================
- *
- *
- */
-static struct dirstuff *
-disk_opendir(char * path)
+//==========================================================================
+// openmem()
+
+int openmem(char * buf, int len)
{
- register struct dirstuff * dirp;
- register int fd;
-
- dirp = (struct dirstuff *)malloc(sizeof(struct dirstuff));
- if (dirp == (struct dirstuff *)-1)
- return 0;
+ int fdesc;
+ struct iob * io;
- DPRINT(("Calling open in opendir\n"));
- fd = open(path,0);
- if (fd == -1) {
- DPRINT(("open failed \n"));
- free((void *)dirp);
- return 0;
- }
+ // Locate a free descriptor slot.
- DPRINT(("open ok fd is %d \n", fd));
- dirp->io = &iob[fd];
- dirp->loc = 0;
- iob[fd].dirbuf_blkno = -1;
+ for (fdesc = 0; fdesc < NFILES; fdesc++)
+ if (iob[fdesc].i_flgs == 0)
+ goto gotfile;
- return dirp;
-}
+ stop("Out of file descriptors");
-/*==========================================================================
- *
- *
- */
-static int
-disk_closedir(struct dirstuff * dirp)
-{
- close(dirp->io - iob);
- free((void *)dirp);
- return 0;
-}
+gotfile:
+ io = &iob[fdesc];
+ bzero(io, sizeof(*io));
-/*==========================================================================
- * get next entry in a directory.
- */
-static struct direct *
-disk_readdir(struct dirstuff * dirp)
-{
- struct direct * dp;
- register struct iob * io;
- daddr_t lbn, d;
- int off;
-#if DCACHE
- char * bp;
- int dirblkno;
-
- if (dcache == 0)
- dcache = cacheInit(DCACHE_SIZE, DIRBLKSIZ);
-#endif DCACHE
-
- io = dirp->io;
- for(;;)
- {
- if (dirp->loc >= io->i_ino.i_size)
- return (NULL);
- off = blkoff(io->i_ffs, dirp->loc);
- lbn = lblkno(io->i_ffs, dirp->loc);
-
-#if DCACHE
- dirblkno = dirp->loc / DIRBLKSIZ;
- if (cacheFind(dcache, io->i_ino.i_number, dirblkno, &bp)) {
- dp = (struct direct *)(bp + (dirp->loc % DIRBLKSIZ));
- } else
-#else DCACHE
- if (io->dirbuf_blkno != lbn)
-#endif DCACHE
- {
- if((d = sbmap(io, lbn)) == 0)
- return NULL;
- io->i_bn = fsbtodb(io->i_ffs, d) + io->i_boff;
- io->i_ma = io->i_buf;
- io->i_cc = blksize(io->i_ffs, &io->i_ino, lbn);
-
- if (devread(io) < 0)
- {
-#if SYS_MESSAGES
- error("bn %d: directory read error\n", io->i_bn);
-#endif
- return (NULL);
- }
-#if BIG_ENDIAN_INTEL_FS
- byte_swap_dir_block_in(io->i_buf, io->i_cc);
-#endif /* BIG_ENDIAN_INTEL_FS */
-
-#if DCACHE
- bcopy(io->i_buf + dirblkno * DIRBLKSIZ, bp, DIRBLKSIZ);
- dp = (struct direct *)(io->i_buf + off);
-#endif
- }
-#if !DCACHE
- dp = (struct direct *)(io->i_buf + off);
-#endif
- dirp->loc += dp->d_reclen;
-
- if (dp->d_ino != 0) return (dp);
- }
-}
+ // Mark the descriptor as taken. Set the F_MEM flag to indicate
+ // that the file buffer is provided by the caller.
-/*==========================================================================
- *
- *
- */
-static ino_t
-dlook(
- char * s,
- struct iob * io
-)
-{
- struct direct * dp;
- register struct inode * ip;
- struct dirstuff dirp;
- int len;
-
- if (s == NULL || *s == '\0')
- return (0);
- ip = &io->i_ino;
- if ((ip->i_mode & IFMT) != IFDIR) {
-#if SYS_MESSAGES
- error(". before %s not a dir\n", s);
-#endif
- return (0);
- }
- if (ip->i_size == 0) {
-#if SYS_MESSAGES
- error("%s: 0 length dir\n", s);
-#endif
- return (0);
- }
- len = strlen(s);
- dirp.loc = 0;
- dirp.io = io;
- io->dirbuf_blkno = -1;
-
- for (dp = disk_readdir(&dirp); dp != NULL; dp = disk_readdir(&dirp)) {
- DPRINT(("checking name %s\n", dp->d_name));
- if(dp->d_ino == 0)
- continue;
- if (dp->d_namlen == len && !strcmp(s, dp->d_name))
- return (dp->d_ino);
- }
- return (0);
-}
+ io->i_flgs = F_ALLOC | F_MEM;
+ io->i_buf = buf;
+ io->i_filesize = len;
-/*==========================================================================
- *
- *
- */
-static int
-getch(int fdesc)
-{
- register struct iob * io;
- struct fs * fs;
- char * p;
- int c, lbn, off, size, diff;
-
- if ((io = iob_from_fdesc(fdesc)) == 0) {
- return (-1);
- }
-
- RDPRINT(("In getch\n"));
-
- p = io->i_ma;
- if (io->i_cc <= 0) {
- if ((io->i_flgs & F_FILE) != 0) {
- diff = io->i_ino.i_size - io->i_offset;
- if (diff <= 0)
- return (-1);
- fs = io->i_ffs;
- lbn = lblkno(fs, io->i_offset);
-#if 1
- io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
-#else
- io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
-#endif
- off = blkoff(fs, io->i_offset);
- size = blksize(fs, &io->i_ino, lbn);
- } else {
- diff = 0;
-#ifndef SMALL
- io->i_bn = io->i_offset / DEV_BSIZE;
- off = 0;
- size = DEV_BSIZE;
-#endif SMALL
- }
-
- RDPRINT(("gc: bn=%x; off=%x\n",io->i_bn, io->i_offset));
-
- io->i_ma = io->i_buf;
- io->i_cc = size;
- if (devread(io) < 0) {
- return (-1);
- }
- if ((io->i_flgs & F_FILE) != 0) {
- if (io->i_offset - off + size >= io->i_ino.i_size)
- io->i_cc = diff + off;
- io->i_cc -= off;
- }
- p = &io->i_buf[off];
- }
- io->i_cc--;
- io->i_offset++;
- c = (unsigned)*p++;
- io->i_ma = p;
- return (c);
+ return fdesc;
}
-/*==========================================================================
- *
- */
-static int
-disk_read(int fdesc, char * buf, int count)
-{
- int i, size;
- register struct iob * file;
- struct fs * fs;
- int lbn, off;
-
- RDSPRINT(("IN READ\n"));
-
- if ((file = iob_from_fdesc(fdesc)) == 0) {
- return (-1);
- }
-#if CHECK_CAREFULLY
- if ((file->i_flgs&F_READ) == 0) {
- return (-1);
- }
-#endif
- if ((file->i_flgs & F_MEM) != 0) {
-
- RDSPRINT(("In read FMEM\n"));
-
- if (file->i_offset < file->i_boff) {
- if (count > (file->i_boff - file->i_offset))
- count = file->i_boff - file->i_offset;
- bcopy(file->i_buf + file->i_offset, buf, count);
- file->i_offset += count;
- } else {
- count = 0;
- }
- return count;
- }
-
-#ifndef SMALL
- if ((file->i_flgs & F_FILE) == 0) {
- file->i_cc = count;
- file->i_ma = buf;
- file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
-
- RDPRINT(("In read nsmall fbn=%x; offset=%x;", file->i_bn,
- file->i_offset));
- RDSPRINT(("boff=%x\n", file->i_boff));
-
- i = devread(file);
- file->i_offset += count;
- return (i);
- }
-#endif /* SMALL */
-
- if (file->i_offset+count > file->i_ino.i_size)
- count = file->i_ino.i_size - file->i_offset;
-
- RDSPRINT(("In read nsmall count=%x;", count));
-
- if ((i = count) <= 0)
- return (0);
-
- /*
- * While reading full blocks, do I/O into user buffer.
- * Anything else uses getc().
- */
- fs = file->i_ffs;
- while (i) {
- RDSPRINT(("In lread while\n"));
- off = blkoff(fs, file->i_offset);
- lbn = lblkno(fs, file->i_offset);
- size = blksize(fs, &file->i_ino, lbn);
- if (off == 0 && size <= i) {
- file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
- file->i_boff;
- file->i_cc = size;
- file->i_ma = buf;
-
- RDPRINT(("In read->devread\n"));
- RDPRINT(("In read fbn=%x; offset=%x;", file->i_bn,
- file->i_offset));
- RDSPRINT((" boff=%x\n", file->i_boff));
-
- if (devread(file) < 0) {
- return (-1);
- }
- file->i_offset += size;
- file->i_cc = 0;
- buf += size;
- i -= size;
- }
- else {
- RDSPRINT(("IN while nonread\n"));
- size -= off;
- if (size > i)
- size = i;
- i -= size;
- do {
- *buf++ = getch(fdesc);
- } while (--size);
- }
- }
-
- return (count);
-}
+//==========================================================================
+// open() - Open the file specified by 'path' for reading.
-/*==========================================================================
- * Disk (block device) functions.
- */
-static BOOL
-disk_open(char * name, struct iob * file, int how)
+int open(const char * path, int flags)
{
- int i;
-
- file->i_cc = SBSIZE;
-// file->i_bn = (SBLOCK / DEV_BSIZE) + file->i_boff;
- file->i_bn = (SBOFF/label_secsize) + file->i_boff;
- file->i_offset = 0;
-
- if (file->i_ffs == 0) {
- if (fs_block == 0) {
- DPRINT(("No super block; reading one \n"));
- fs_block = (struct fs *) malloc(SBSIZE);
- }
- if (fs_block_valid == 0) {
- file->i_ma = (char *)fs_block;
- if (devread(file) < 0) {
-#ifndef SMALL
- error(SUPERBLOCK_ERROR, 1);
-#endif
- return NO;
- }
-#if BIG_ENDIAN_INTEL_FS
- byte_swap_superblock(fs_block);
-#endif /* BIG_ENDIAN_INTEL_FS */
- DPRINT(("Read SB \n"));
- fs_block_valid = 1;
- }
- file->i_ffs = fs_block;
- file->i_buf = malloc(MAXBSIZE);
- }
-#if BIG_ENDIAN_INTEL_FS
- DPRINT(("IN BE_FS code \n"));
-
- if (file->i_ffs->fs_magic != FS_MAGIC) {
- DPRINT(("Bad magic in FS %d ; got %d\n", FS_MAGIC,
- file->i_ffs->fs_magic));
- error(SUPERBLOCK_ERROR, 2);
- return NO;
- }
- /*
- * The following is a gross hack to boot disks that have an actual
- * blocksize of 512 bytes but were written with a theoretical 1024
- * byte blocksize (fsbtodb == 0).
- *
- * We can make this assumption because we can only boot disks with
- * a 512 byte sector size.
- */
- DPRINT(("SB magic ok \n"));
- if (file->i_ffs->fs_fsize == 0) {
- error(SUPERBLOCK_ERROR,3);
- return NO;
- }
- file->i_ffs->fs_fsbtodb = ffs(file->i_ffs->fs_fsize / DEV_BSIZE) - 1;
-#endif /* BIG_ENDIAN_INTEL_FS */
-
- if ((i = find(name, file)) == 0) {
- DPRINT(("find() failed\n"));
- return NO;
- }
-
-#if CHECK_CAREFULLY
- if (how != 0) {
- error("Can't write files\n");
- return NO;
- }
-#endif CHECK_CAREFULLY
-
- DPRINT(("calling openi \n"));
- if (openi(i, file) < 0) {
- DPRINT(("openi failed \n"));
- return NO;
- }
-
- DPRINT(("openi ok \n"));
-
- file->i_offset = 0;
- file->i_cc = 0;
- file->i_flgs |= F_FILE | (how+1);
-
- return YES;
-}
+ int fdesc, i;
+ struct iob * io;
+ const char * filePath;
+ BVRef bvr;
-/*==========================================================================
- *
- *
- */
-static int
-ffs(register long mask)
-{
- register int cnt;
+ // Locate a free descriptor slot.
- if (mask == 0) return(0);
+ for (fdesc = 0; fdesc < NFILES; fdesc++)
+ if (iob[fdesc].i_flgs == 0)
+ goto gotfile;
- for (cnt = 1; !(mask & 1); cnt++)
- mask >>= 1;
- return(cnt);
-}
+ stop("Out of file descriptors");
-/*==========================================================================
- *
- *
- */
-static void
-disk_flushdev()
-{
- register int i;
-
- devflush();
+gotfile:
+ io = &iob[fdesc];
+ bzero(io, sizeof(*io));
+
+ // Mark the descriptor as taken.
+
+ io->i_flgs = F_ALLOC;
+
+ // Resolve the boot volume from the file spec.
+
+ if ((bvr = getBootVolumeRef(path, &filePath)) == NULL)
+ goto error;
+
+ // Find the next available memory block in the download buffer.
+
+ io->i_buf = (char *) LOAD_ADDR;
for (i = 0; i < NFILES; i++)
- if (iob[i].i_flgs & (F_READ | F_WRITE))
- error("flushdev: fd %d is open\n",i);
-
- fs_block_valid = 0;
-#if ICACHE
- cacheFlush(icache);
-#endif
-#if DCACHE
- cacheFlush(dcache);
-#endif
+ {
+ if ((iob[i].i_flgs != F_ALLOC) || (i == fdesc)) continue;
+ io->i_buf = max(iob[i].i_filesize + iob[i].i_buf, io->i_buf);
+ }
+
+ // Load entire file into memory. Unnecessary open() calls must
+ // be avoided.
+
+ gFSLoadAddress = io->i_buf;
+ io->i_filesize = bvr->fs_loadfile(bvr, (char *)filePath);
+ if (io->i_filesize < 0) goto error;
+
+ return fdesc;
+
+error:
+ close(fdesc);
+ return -1;
}
-/***************************************************************************
- *
- * Network functions.
- *
- ***************************************************************************/
+//==========================================================================
+// close() - Close a file descriptor.
-static int
-en_read(int fdesc, char * buf, int count)
+int close(int fdesc)
{
- struct iob * file;
+ struct iob * io;
- if ((file = iob_from_fdesc(fdesc)) == 0)
- return (-1);
-
- DSPRINT(("read[%d]: %x %x %d\n",
- fdesc, TFTP_ADDR + file->i_offset, (unsigned) buf, count));
+ if ((io = iob_from_fdesc(fdesc)) == NULL)
+ return (-1);
- bcopy((char *)(TFTP_ADDR + file->i_offset), buf, count);
- file->i_offset += count;
+ io->i_flgs = 0;
- return count;
+ return 0;
}
-
-static BOOL
-en_open(char * name, struct iob * file, int how)
+
+//==========================================================================
+// lseek() - Reposition the byte offset of the file descriptor from the
+// beginning of the file. Returns the relocated offset.
+
+int b_lseek(int fdesc, int offset, int ptr)
{
- unsigned long txferSize = TFTP_LEN;
-
- if (nbpTFTPReadFile(name, &txferSize, TFTP_ADDR) != nbpStatusSuccess)
- return NO;
+ struct iob * io;
- file->i_buf = NULL;
- file->i_offset = 0;
- file->i_ino.i_size = txferSize; // update the real size
+ if ((io = iob_from_fdesc(fdesc)) == NULL)
+ return (-1);
- return YES;
-}
+ io->i_offset = offset;
-static void
-en_devopen(char * name, struct iob * io)
-{
- io->i_error = 0;
+ return offset;
}
-/***************************************************************************
- *
- * Dispatch functions.
- *
- ***************************************************************************/
+//==========================================================================
+// tell() - Returns the byte offset of the file descriptor.
-/*==========================================================================
- *
- */
-static int
-gen_read(int fdesc, char * buf, int count)
+int tell(int fdesc)
{
- struct iob * file;
-
- if ((file = iob_from_fdesc(fdesc)) == 0)
- return (-1);
-
- return (file->i_ino.i_dev == DEV_EN) ?
- en_read(fdesc, buf, count) :
- disk_read(fdesc, buf, count);
-}
+ struct iob * io;
-/*==========================================================================
- *
- */
-static int
-gen_open(char * name, struct iob * file, int how)
-{
- return (file->i_ino.i_dev == DEV_EN) ?
- en_open(name, file, how) : disk_open(name, file, how);
+ if ((io = iob_from_fdesc(fdesc)) == NULL)
+ return 0;
+
+ return io->i_offset;
}
-/*==========================================================================
- *
- */
-static void
-gen_devopen(char * name, struct iob * io)
+//==========================================================================
+// read() - Read up to 'count' bytes of data from the file descriptor
+// into the buffer pointed to by buf.
+
+int read(int fdesc, char * buf, int count)
{
- return (io->i_ino.i_dev == DEV_EN) ?
- en_devopen(name, io) : devopen(name, io);
+ struct iob * io;
+
+ if ((io = iob_from_fdesc(fdesc)) == NULL)
+ return (-1);
+
+ if (io->i_offset + count > io->i_filesize)
+ count = io->i_filesize - io->i_offset;
+
+ if (count <= 0)
+ return 0; // end of file
+
+ bcopy(io->i_buf + io->i_offset, buf, count);
+
+ io->i_offset += count;
+
+ return count;
}
-/*==========================================================================
- *
- */
-static void
-gen_flushdev()
+//==========================================================================
+// file_size() - Returns the size of the file described by the file
+// descriptor.
+
+int file_size(int fdesc)
{
- return disk_flushdev();
+ struct iob * io;
+
+ if ((io = iob_from_fdesc(fdesc)) == 0)
+ return 0;
+
+ return io->i_filesize;
}
-/*==========================================================================
- *
- */
-static char *
-gen_usrDevices()
+//==========================================================================
+
+struct dirstuff * opendir(const char * path)
{
-#define NET_ARCH_DEVICES ""
+ struct dirstuff * dirp = 0;
+ const char * dirPath;
+ BVRef bvr;
+
+ if ((bvr = getBootVolumeRef(path, &dirPath)) == NULL)
+ goto error;
+
+ dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff));
+ if (dirp == NULL)
+ goto error;
+
+ dirp->dir_path = newString(dirPath);
+ if (dirp->dir_path == NULL)
+ goto error;
+
+ dirp->dir_bvr = bvr;
+
+ return dirp;
- return (((currentdev() >> B_TYPESHIFT) & B_TYPEMASK) == DEV_EN) ?
- NET_ARCH_DEVICES : ARCH_DEVICES;
+error:
+ closedir(dirp);
+ return NULL;
}
-/***************************************************************************
- *
- * External functions.
- *
- ***************************************************************************/
+//==========================================================================
-/*==========================================================================
- *
- */
-struct dirstuff *
-opendir(char * path)
+int closedir(struct dirstuff * dirp)
{
- return disk_opendir(path);
+ if (dirp) {
+ if (dirp->dir_path) free(dirp->dir_path);
+ free(dirp);
+ }
+ return 0;
}
-/*==========================================================================
- *
- */
-int
-closedir(struct dirstuff * dirp)
+//==========================================================================
+
+int readdir(struct dirstuff * dirp, const char ** name, long * flags,
+ long * time)
{
- return disk_closedir(dirp);
+ return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr,
+ /* dirPath */ dirp->dir_path,
+ /* dirIndex */ &dirp->dir_index,
+ /* dirEntry */ (char **)name, flags, time );
}
-/*==========================================================================
- * get next entry in a directory.
- */
-struct direct *
-readdir(struct dirstuff * dirp)
+//==========================================================================
+
+int currentdev()
{
- return disk_readdir(dirp);
+ return kernBootStruct->kernDev;
}
-/*==========================================================================
- *
- */
-int
-b_lseek(int fdesc, unsigned int addr, int ptr)
+//==========================================================================
+
+int switchdev(int dev)
{
- register struct iob * io;
+ kernBootStruct->kernDev = dev;
+ return dev;
+}
- RDPRINT(("In lseek addr= %x\n", addr));
+//==========================================================================
-#if CHECK_CAREFULLY
- if (ptr != 0) {
- error("Seek not from beginning of file\n");
- return (-1);
- }
-#endif /* CHECK_CAREFULLY */
+const char * usrDevices()
+{
+ return (B_TYPE(currentdev()) == DEV_EN) ? "" : "/private/Drivers/i386";
+}
- if ((io = iob_from_fdesc(fdesc)) == 0) {
- return (-1);
- }
- io->i_offset = addr;
- io->i_bn = addr / DEV_BSIZE;
- io->i_cc = 0;
+//==========================================================================
- RDPRINT(("In end of lseek offset %x; bn %x\n", io->i_offset,io->i_bn));
+BVRef scanBootVolumes( int biosdev, int * count )
+{
+ BVRef bvr = 0;
- return (0);
+ switch ( BIOS_DEV_TYPE( biosdev ) )
+ {
+ case kBIOSDevTypeFloppy:
+ case kBIOSDevTypeHardDrive:
+ bvr = diskScanBootVolumes( biosdev, count );
+ break;
+ case kBIOSDevTypeNetwork:
+ bvr = nbpScanBootVolumes( biosdev, count );
+ break;
+ }
+ return bvr;
}
-/*==========================================================================
- *
- */
-int
-tell(int fdesc)
-{
- return iob[fdesc].i_offset;
-}
+//==========================================================================
-/*==========================================================================
- *
- */
-int
-read(int fdesc, char * buf, int count)
+void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen )
{
- return gen_read(fdesc, buf, count);
+ bvr->description( bvr, str, strMaxLen );
}
-/*==========================================================================
- *
- */
-int
-openmem(char * buf, int len)
-{
- register struct iob * file;
- int fdesc;
+//==========================================================================
- for (fdesc = 0; fdesc < NFILES; fdesc++)
- if (iob[fdesc].i_flgs == 0)
- goto gotfile;
- stop("Out of file descriptor slots");
+BVRef selectBootVolume( BVRef chain )
+{
+ BVRef bvr, bvr1 = 0, bvr2 = 0;
-gotfile:
- (file = &iob[fdesc])->i_flgs |= F_ALLOC;
- file->i_buf = buf;
- file->i_boff = len;
- file->i_offset = 0;
- file->i_flgs |= F_MEM;
- return fdesc;
-}
+ for ( bvr = chain; bvr; bvr = bvr->next )
+ {
+ if ( bvr->flags & kBVFlagNativeBoot ) bvr1 = bvr;
+ if ( bvr->flags & kBVFlagPrimary ) bvr2 = bvr;
+ }
-/*==========================================================================
- * Generic open call.
- */
-int
-open(char * str, int how)
-{
- register char * cp;
- register struct iob * file;
- int fdesc;
-
- DSPRINT(("In open %s\n", str));
-
-#if CHECK_CAREFULLY /* iob[] is in BSS, so it is guaranteed to be zero. */
- if (open_init == 0) {
- int i;
- for (i = 0; i < NFILES; i++)
- iob[i].i_flgs = 0;
- open_init = 1;
- }
-#endif
-
- for (fdesc = 0; fdesc < NFILES; fdesc++)
- if (iob[fdesc].i_flgs == 0)
- goto gotfile;
- stop("Out of file descriptor slots");
+ bvr = bvr1 ? bvr1 :
+ bvr2 ? bvr2 : chain;
-gotfile:
- (file = &iob[fdesc])->i_flgs |= F_ALLOC;
-
- if ((cp = xx(str, file)) == (char *) -1)
- {
- close(fdesc);
- return -1;
- }
-
- if (*cp == '\0') {
- file->i_flgs |= how+1;
- file->i_cc = 0;
- file->i_offset = 0;
- return (fdesc);
- }
-
- if (gen_open(cp, file, how) == NO) {
- close(fdesc);
- return -1;
- }
- return (fdesc);
+ return bvr;
}
-/*==========================================================================
- *
- */
+//==========================================================================
+
#define LP '('
#define RP ')'
+extern int gBIOSDev;
-static char * xx(char *str, struct iob *file)
+static BVRef getBootVolumeRef( const char * path, const char ** outPath )
{
- register char *cp = str, *xp;
- char ** dp;
- int old_dev = kernBootStruct->kernDev;
- int dev = (kernBootStruct->kernDev >> B_TYPESHIFT) & B_TYPEMASK;
- int unit = (kernBootStruct->kernDev >> B_UNITSHIFT) & B_UNITMASK;
- int part = (kernBootStruct->kernDev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
- int i;
- int no_dev;
- int biosOffset;
-
- biosOffset = unit; // set the device
-
- for (; *cp && *cp != LP; cp++) ;
- if (no_dev = !*cp) { // no left paren found
- cp = str;
- xp = devsw[dev];
- } else if (cp == str) { // paren but no device
- cp++;
- xp = devsw[dev];
- } else {
- xp = str;
- cp++;
- }
-
- for (dp = devsw; *dp; dp++)
- {
- if ((xp[0] == *dp[0]) && (xp[1] == *(dp[0] + 1)))
- goto gotdev;
- }
-
- error("Unknown device '%c%c'\n",xp[0],xp[1]);
- return ((char *)-1);
-
-gotdev:
- if (no_dev)
- goto none;
- i = 0;
- while (*cp >= '0' && *cp <= '9')
- {
- i = i * 10 + *cp++ - '0';
- unit = i; // get the specified unit number
- }
-
- biosOffset = unit; // set the device
-
- if (*cp == RP || no_dev)
- /* do nothing since ptol(")") returns 0 */ ;
- else if (*cp == ',')
- part = ptol(++cp); // get the specified partition number
- else if (cp[-1] == LP)
- part = ptol(cp);
- else {
-badoff:
- error("Missing offset specification\n");
- return ((char *)-1);
- }
-
- for ( ;!no_dev ;) { // skip after the right paren
- if (*cp == RP)
- break;
- if (*cp++)
- continue;
- goto badoff;
- }
-
-none:
- file->i_ino.i_dev = dev = dp - devsw;
- file->partition = part;
- file->biosdev = (BIOSDEV(dev)) + biosOffset;
-
- if (dev == DEV_SD) {
- file->biosdev += kernBootStruct->numIDEs;
- }
- else if (dev == DEV_EN) {
- file->biosdev = BIOS_DEV_EN;
+ const char * cp;
+ BVRef bvr;
+ int type = B_TYPE( kernBootStruct->kernDev );
+ int unit = B_UNIT( kernBootStruct->kernDev );
+ int part = B_PARTITION( kernBootStruct->kernDev );
+ int biosdev = gBIOSDev;
+ static BVRef lastBVR = 0;
+ static int lastKernDev;
+
+ // Search for left parenthesis in the path specification.
+
+ for (cp = path; *cp; cp++) {
+ if (*cp == LP || *cp == '/') break;
}
- else if (dev == DEV_HD && kernBootStruct->numIDEs == 0) {
- error("No IDE drives detected\n");
- return ((char *)-1);
- }
- kernBootStruct->kernDev = (dev << B_TYPESHIFT) |
- (unit << B_UNITSHIFT) |
- (part << B_PARTITIONSHIFT);
+ if (*cp != LP) // no left paren found
+ {
+ cp = path;
+ if ( lastBVR && lastKernDev == kernBootStruct->kernDev )
+ {
+ bvr = lastBVR;
+ goto quick_exit;
+ }
+ }
+ else if ((cp - path) == 2) // found "xx("
+ {
+ const struct devsw * dp;
+ const char * xp = path;
+ int i;
+
+ cp++;
+
+ // Check the 2 character device name pointed by 'xp'.
+
+ for (dp = devsw; dp->name; dp++)
+ {
+ if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1]))
+ break; // found matching entry
+ }
+ if (dp->name == NULL)
+ {
+ error("Unknown device '%c%c'\n", xp[0], xp[1]);
+ return NULL;
+ }
+ type = dp - devsw; // kerndev type
+
+ // Extract the optional unit number from the specification.
+ // hd(unit) or hd(unit, part).
+
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ {
+ i = i * 10 + *cp++ - '0';
+ unit = i;
+ }
+
+ // Extract the optional partition number from the specification.
+
+ if (*cp == ',')
+ part = atoi(++cp);
+
+ // Skip past the right paren.
+
+ for ( ; *cp && *cp != RP; cp++) /* LOOP */;
+ if (*cp == RP) cp++;
+
+ biosdev = dp->biosdev;
+ }
+ else
+ {
+ // Bad device specifier, skip past the right paren.
- if (kernBootStruct->kernDev != old_dev)
- flushdev();
+ for ( cp++; *cp && *cp != RP; cp++) /* LOOP */;
+ if (*cp == RP) cp++;
+ }
- gen_devopen(str, file);
+ biosdev += (unit & kBIOSDevUnitMask);
- if (file->i_error)
- return (char *)-1;
- if (!no_dev && *cp) cp++;
+ if ((bvr = newBootVolumeRef(biosdev, part)) == NULL)
+ {
+ // error("newBootVolumeRef() error\n");
+ return NULL;
+ }
- gFilename = cp;
+ // Record the most recent device parameters in the
+ // KernBootStruct.
- return cp;
-}
+ kernBootStruct->kernDev = MAKEKERNDEV(type, unit, bvr->part_no);
-/*==========================================================================
- *
- */
-int
-close(int fdesc)
-{
- register struct iob * file;
- register int i;
-
- if ((file = iob_from_fdesc(fdesc)) == 0)
- return (-1);
-
- if ((file->i_flgs & F_MEM) == 0) {
-// free((char *)file->i_ffs);
- file->i_ffs = NULL;
- if (file->i_buf) {
- free(file->i_buf);
- file->i_buf = NULL;
- }
- for (i=0;i<NBUFS;i++)
- {
- if (b[i])
- { free(b[i]);
- b[i] = NULL;
- }
- blknos[i] = 0;
- }
- }
-
- file->i_flgs = 0;
- return (0);
-}
+ lastBVR = bvr;
+ lastKernDev = kernBootStruct->kernDev;
-/*==========================================================================
- *
- */
-int
-file_size(int fdesc)
-{
- register struct iob * io;
-
- if ((io = iob_from_fdesc(fdesc)) == 0)
- return (-1);
+quick_exit:
+ // Returns the file path following the device spec.
+ // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
- return io->i_ino.i_size;
-}
+ *outPath = cp;
-/*==========================================================================
- * ensure that all device caches are flushed,
- * because we are about to change the device media
- */
-void
-flushdev()
-{
- gen_flushdev();
+ return bvr;
}
-/*==========================================================================
- *
- */
-void
-stop(char * s)
-{
-#if CHECK_CAREFULLY
- register int i;
-
- for (i = 0; i < NFILES; i++)
- if (iob[i].i_flgs != 0)
- close(i);
-#endif CHECK_CAREFULLY
-
- /* textMode(); */ // can't call this function from here
- error("\n%s\n", s);
- sleep(4); // about to halt
- halt();
-}
+//==========================================================================
-/*==========================================================================
- *
- */
-int currentdev()
+static BVRef newBootVolumeRef( int biosdev, int partno )
{
- return kernBootStruct->kernDev;
-}
+ BVRef bvr, bvr1, bvrChain;
-/*==========================================================================
- *
- */
-int
-switchdev(int dev)
-{
- flushdev();
- kernBootStruct->kernDev = dev;
- return dev;
-}
+ // Fetch the volume list from the device.
-/*==========================================================================
- *
- */
-char *
-usrDevices()
-{
- return gen_usrDevices();
+ bvrChain = scanBootVolumes( biosdev, NULL );
+
+ // Look for a perfect match based on device and partition number.
+
+ for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next )
+ {
+ if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue;
+
+ bvr1 = bvr;
+ if ( bvr->part_no == partno ) break;
+ }
+
+ return bvr ? bvr : bvr1;
}
#include "memory.h"
-#define NGDTENT 6
-#define GDTLIMIT 48 /* NGDTENT * 8 */
-
/* Segment Descriptor
*
* 31 24 19 16 7 0
*/
struct seg_desc {
- unsigned short limit_15_0;
- unsigned short base_15_0;
- unsigned char base_23_16;
- unsigned char bit_15_8;
- unsigned char bit_23_16;
- unsigned char base_31_24;
- };
+ unsigned short limit_15_0;
+ unsigned short base_15_0;
+ unsigned char base_23_16;
+ unsigned char bit_15_8;
+ unsigned char bit_23_16;
+ unsigned char base_31_24;
+};
+struct seg_desc Gdt[ NGDTENT ] = {
+ /* 0x0 : null */
+ {0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
-struct seg_desc Gdt[NGDTENT] = {
- {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* 0x0 : null */
- // byte granularity, 1Mb limit, MEMBASE offset
- {0xFFFF, MEMBASE, 0x0, 0x9E, 0x4F, 0x0}, /* 0x8 : boot code */
- // dword granularity, 2Gb limit, MEMBASE offset
- {0xFFFF, MEMBASE, 0x0, 0x92, 0xCF, 0x0}, /* 0x10 : boot data */
- {0xFFFF, MEMBASE, 0x0, 0x9E, 0xF, 0x0}, /* 0x18 : boot code, 16 bits */
- {0xFFFF, 0x0, 0x0, 0x92, 0xCF, 0x0}, /* 0x20 : init data */
- {0xFFFF, 0x0, 0x0, 0x9E, 0xCF, 0x0} /* 0x28 : init code */
-};
+ /* 0x8 : boot protected mode 32-bit code segment
+ byte granularity, 1MB limit, MEMBASE offset */
+ {0xFFFF, MEMBASE, 0x00, 0x9E, 0x4F, 0x00},
+
+ /* 0x10 : boot protected mode data segment
+ page granularity, 4GB limit, MEMBASE offset */
+ {0xFFFF, MEMBASE, 0x00, 0x92, 0xCF, 0x00},
+
+ /* 0x18 : boot protected mode 16-bit code segment
+ byte granularity, 1MB limit, MEMBASE offset */
+ {0xFFFF, MEMBASE, 0x00, 0x9E, 0x0F, 0x00},
+ /* 0x20 : kernel init 32-bit data segment
+ page granularity, 4GB limit, zero offset */
+ {0xFFFF, 0x0000, 0x00, 0x92, 0xCF, 0x00},
+
+ /* 0x28 : kernel init 32-bit code segment
+ page granularity, 4GB limit, zero offset */
+ {0xFFFF, 0x0000, 0x00, 0x9E, 0xCF, 0x00},
+
+ /* 0x30 : boot real mode data/stack segment
+ byte granularity, 64K limit, MEMBASE offset, expand-up */
+ {0xFFFF, MEMBASE, 0x00, 0x92, 0x00, 0x00},
+};
--- /dev/null
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * ufs.c - File System Module for UFS.
+ *
+ * Copyright (c) 1998-2002 Apple Computer, Inc.
+ *
+ * DRI: Josh de Cesare
+ */
+
+#include <sl.h>
+
+#include "ufs_byteorder.h"
+
+typedef struct dinode Inode, *InodePtr;
+
+// Private function prototypes
+
+static char *ReadBlock(long fragNum, long fragOffset, long length,
+ char *buffer, long cache);
+static long ReadInode(long inodeNum, InodePtr inode, long *flags, long *time);
+static long ResolvePathToInode(char *filePath, long *flags,
+ InodePtr fileInode, InodePtr dirInode);
+static long ReadDirEntry(InodePtr dirInode, long *fileInodeNum,
+ long *dirIndex, char **name);
+static long FindFileInDir(char *fileName, long *flags,
+ InodePtr fileInode, InodePtr dirInode);
+static char *ReadFileBlock(InodePtr fileInode, long fragNum, long blockOffset,
+ long length, char *buffer, long cache);
+static long ReadFile(InodePtr fileInode, long *length);
+
+#define kDevBlockSize (0x200) // Size of each disk block.
+#define kDiskLableBlock (15) // Block the DL is in.
+
+#ifdef __i386__
+
+static CICell gCurrentIH;
+static long long gPartitionBase;
+static char *gDLBuf;
+static char *gFSBuf;
+static struct fs *gFS;
+static long gBlockSize;
+static long gFragSize;
+static long gFragsPerBlock;
+static char *gTempBlock;
+static char *gTempName;
+static char *gTempName2;
+static InodePtr gRootInodePtr;
+static InodePtr gFileInodePtr;
+
+#else /* !__i386__ */
+
+static CICell gCurrentIH;
+static long long gPartitionBase;
+static char gDLBuf[8192];
+static char gFSBuf[SBSIZE];
+static struct fs *gFS;
+static long gBlockSize;
+static long gFragSize;
+static long gFragsPerBlock;
+static char *gTempBlock;
+static char gTempName[MAXNAMLEN + 1];
+static char gTempName2[MAXNAMLEN + 1];
+static Inode _gRootInode;
+static Inode _gFileInode;
+static InodePtr gRootInodePtr = &_gRootInode;
+static InodePtr gFileInodePtr = &_gFileInode;
+
+#endif /* !__i386__ */
+
+// Public functions
+
+long UFSInitPartition( CICell ih )
+{
+ if (ih == gCurrentIH) {
+#ifdef __i386__
+ CacheInit(ih, gBlockSize);
+#endif
+ return 0;
+ }
+
+ verbose("UFSInitPartition: %x\n", ih);
+
+ gCurrentIH = 0;
+
+#ifdef __i386__
+ if (!gDLBuf) gDLBuf = (char *) malloc(8192);
+ if (!gFSBuf) gFSBuf = (char *) malloc(SBSIZE);
+ if (!gTempName) gTempName = (char *) malloc(MAXNAMLEN + 1);
+ if (!gTempName2) gTempName2 = (char *) malloc(MAXNAMLEN + 1);
+ if (!gRootInodePtr) gRootInodePtr = (InodePtr) malloc(sizeof(Inode));
+ if (!gFileInodePtr) gFileInodePtr = (InodePtr) malloc(sizeof(Inode));
+ if (!gDLBuf || !gFSBuf || !gTempName || !gTempName2 ||
+ !gRootInodePtr || !gFileInodePtr) return -1;
+#endif
+
+ // Assume there is no Disk Label
+ gPartitionBase = 0;
+
+ // Look for the Super Block
+ Seek(ih, gPartitionBase + SBOFF);
+ Read(ih, (long)gFSBuf, SBSIZE);
+
+ gFS = (struct fs *)gFSBuf;
+ byte_swap_superblock(gFS);
+
+ if (gFS->fs_magic != FS_MAGIC) {
+#ifdef __i386__
+ return -1; // not yet for Intel
+#else /* !__i386__ */
+ disk_label_t *dl;
+ partition_t *part;
+
+ // Did not find it... Look for the Disk Label.
+ // Look for the Disk Label
+ Seek(ih, 1ULL * kDevBlockSize * kDiskLableBlock);
+ Read(ih, (long)gDLBuf, 8192);
+
+ dl = (disk_label_t *)gDLBuf;
+ byte_swap_disklabel_in(dl);
+
+ if (dl->dl_version != DL_VERSION) {
+ return -1;
+ }
+
+ part = &dl->dl_part[0];
+ gPartitionBase = (1ULL * (dl->dl_front + part->p_base) * dl->dl_secsize) -
+ (1ULL * (dl->dl_label_blkno - kDiskLableBlock) * kDevBlockSize);
+
+ // Re-read the Super Block.
+ Seek(ih, gPartitionBase + SBOFF);
+ Read(ih, (long)gFSBuf, SBSIZE);
+
+ gFS = (struct fs *)gFSBuf;
+ if (gFS->fs_magic != FS_MAGIC) {
+ return -1;
+ }
+#endif /* !__i386__ */
+ }
+
+ // Calculate the block size and set up the block cache.
+ gBlockSize = gFS->fs_bsize;
+ gFragSize = gFS->fs_fsize;
+ gFragsPerBlock = gBlockSize / gFragSize;
+ if (gTempBlock != 0) free(gTempBlock);
+ gTempBlock = malloc(gBlockSize);
+ CacheInit(ih, gBlockSize);
+
+ gCurrentIH = ih;
+
+ // Read the Root Inode
+ ReadInode(ROOTINO, gRootInodePtr, 0, 0);
+
+ return 0;
+}
+
+long UFSLoadFile( CICell ih, char * filePath )
+{
+ long ret, length, flags;
+
+ if (UFSInitPartition(ih) == -1) return -1;
+
+ verbose("Loading UFS file: [%s] from %x.\n", filePath, (unsigned)ih);
+
+ // Skip one or two leading '/'.
+ if (*filePath == '/') filePath++;
+ if (*filePath == '/') filePath++;
+
+ ret = ResolvePathToInode(filePath, &flags, gFileInodePtr, gRootInodePtr);
+ if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) return -1;
+
+#if 0
+ // System.config/Default.table will fail this check.
+ // Turn this back on when usage of System.config is deprecated.
+ if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1;
+#endif
+
+ ret = ReadFile(gFileInodePtr, &length);
+ if (ret == -1) return -1;
+
+ return length;
+}
+
+long UFSGetDirEntry( CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time )
+{
+ long ret, fileInodeNum, dirFlags;
+ Inode tmpInode;
+
+ if (UFSInitPartition(ih) == -1) return -1;
+
+ // Skip a leading '/' if present
+ if (*dirPath == '/') dirPath++;
+ if (*dirPath == '/') dirPath++;
+
+ ret = ResolvePathToInode(dirPath, &dirFlags, gFileInodePtr, gRootInodePtr);
+ if ((ret == -1) || ((dirFlags & kFileTypeMask) != kFileTypeDirectory))
+ return -1;
+
+ ret = ReadDirEntry(gFileInodePtr, &fileInodeNum, dirIndex, name);
+ if (ret != 0) return ret;
+
+ ReadInode(fileInodeNum, &tmpInode, flags, time);
+
+ return 0;
+}
+
+// Private functions
+
+static char * ReadBlock( long fragNum, long blockOffset, long length,
+ char * buffer, long cache )
+{
+ long long offset;
+ long blockNum;
+
+ blockNum = fragNum / gFragsPerBlock;
+ fragNum -= blockNum * gFragsPerBlock;
+
+ blockOffset += fragNum * gFragSize;
+
+ offset = gPartitionBase + 1ULL * blockNum * gBlockSize;
+
+ if (cache && ((blockOffset + length) <= gBlockSize)) {
+ CacheRead(gCurrentIH, gTempBlock, offset, gBlockSize, 1);
+ if (buffer != 0) bcopy(gTempBlock + blockOffset, buffer, length);
+ else buffer = gTempBlock + blockOffset;
+ } else {
+ offset += blockOffset;
+ CacheRead(gCurrentIH, buffer, offset, length, 0);
+ }
+
+ return buffer;
+}
+
+static long ReadInode( long inodeNum, InodePtr inode, long * flags, long * time )
+{
+ long fragNum = ino_to_fsba(gFS, inodeNum);
+ long blockOffset = ino_to_fsbo(gFS, inodeNum) * sizeof(Inode);
+
+ ReadBlock(fragNum, blockOffset, sizeof(Inode), (char *)inode, 1);
+ byte_swap_dinode_in(inode);
+
+ if (time != 0) *time = inode->di_mtime;
+
+ if (flags != 0) {
+ switch (inode->di_mode & IFMT) {
+ case IFREG: *flags = kFileTypeFlat; break;
+ case IFDIR: *flags = kFileTypeDirectory; break;
+ case IFLNK: *flags = kFileTypeLink; break;
+ default : *flags = kFileTypeUnknown; break;
+ }
+
+ *flags |= inode->di_mode & kPermMask;
+
+ if (inode->di_uid != 0) *flags |= kOwnerNotRoot;
+ }
+
+ return 0;
+}
+
+static long ResolvePathToInode( char * filePath, long * flags,
+ InodePtr fileInode, InodePtr dirInode )
+{
+ char * restPath;
+ long ret, cnt;
+
+ // if filePath is empty the we want this directory.
+ if (*filePath == '\0') {
+ bcopy((char *)dirInode, (char *)fileInode, sizeof(Inode));
+ return 0;
+ }
+
+ // Copy the file name to gTempName
+ cnt = 0;
+ while ((filePath[cnt] != '/') && (filePath[cnt] != '\0')) cnt++;
+ strncpy(gTempName, filePath, cnt);
+
+ // Move restPath to the right place.
+ if (filePath[cnt] != '\0') cnt++;
+ restPath = filePath + cnt;
+
+ // gTempName is a name in the current Dir.
+ // restPath is the rest of the path if any.
+
+ ret = FindFileInDir(gTempName, flags, fileInode, dirInode);
+ if (ret == -1) return -1;
+
+ if ((*restPath != '\0') && ((*flags & kFileTypeMask) == kFileTypeDirectory))
+ ret = ResolvePathToInode(restPath, flags, fileInode, fileInode);
+
+ return ret;
+}
+
+static long ReadDirEntry( InodePtr dirInode, long * fileInodeNum,
+ long * dirIndex, char ** name )
+{
+ struct direct *dir;
+ char *buffer;
+ long index;
+ long dirBlockNum, dirBlockOffset;
+
+ while (1) {
+ index = *dirIndex;
+
+ dirBlockOffset = index % DIRBLKSIZ;
+ dirBlockNum = index / DIRBLKSIZ;
+
+ buffer = ReadFileBlock(dirInode, dirBlockNum, 0, DIRBLKSIZ, 0, 1);
+ if (buffer == 0) return -1;
+
+ dir = (struct direct *)(buffer + dirBlockOffset);
+ byte_swap_dir_block_in((char *)dir, 1);
+
+ *dirIndex += dir->d_reclen;
+
+ if (dir->d_ino != 0) break;
+
+ if (dirBlockOffset != 0) return -1;
+ }
+
+ *fileInodeNum = dir->d_ino;
+ *name = strncpy(gTempName2, dir->d_name, dir->d_namlen);
+
+ return 0;
+}
+
+static long FindFileInDir( char * fileName, long * flags,
+ InodePtr fileInode, InodePtr dirInode )
+{
+ long ret, inodeNum, index = 0;
+ char *name;
+
+ while (1) {
+ ret = ReadDirEntry(dirInode, &inodeNum, &index, &name);
+ if (ret == -1) return -1;
+
+ if (strcmp(fileName, name) == 0) break;
+ }
+
+ ReadInode(inodeNum, fileInode, flags, 0);
+
+ return 0;
+}
+
+static char * ReadFileBlock( InodePtr fileInode, long fragNum, long blockOffset,
+ long length, char * buffer, long cache )
+{
+ long fragCount, blockNum;
+ long diskFragNum, indFragNum, indBlockOff, refsPerBlock;
+ char *indBlock;
+
+ fragCount = (fileInode->di_size + gFragSize - 1) / gFragSize;
+ if (fragNum >= fragCount) return 0;
+
+ refsPerBlock = gBlockSize / sizeof(ufs_daddr_t);
+
+ blockNum = fragNum / gFragsPerBlock;
+ fragNum -= blockNum * gFragsPerBlock;
+
+ // Get Direct Block Number.
+ if (blockNum < NDADDR) {
+ diskFragNum = fileInode->di_db[blockNum];
+ } else {
+ blockNum -= NDADDR;
+
+ // Get Single Indirect Fragment Number.
+ if (blockNum < refsPerBlock) {
+ indFragNum = fileInode->di_ib[0];
+ } else {
+ blockNum -= refsPerBlock;
+
+ // Get Double Indirect Fragment Number.
+ if (blockNum < (refsPerBlock * refsPerBlock)) {
+ indFragNum = fileInode->di_ib[1];
+ } else {
+ blockNum -= refsPerBlock * refsPerBlock;
+
+ // Get Triple Indirect Fragment Number.
+ indFragNum = fileInode->di_ib[2];
+
+ indBlock = ReadBlock(indFragNum, 0, gBlockSize, 0, 1);
+ indBlockOff = blockNum / (refsPerBlock * refsPerBlock);
+ blockNum %= (refsPerBlock * refsPerBlock);
+ indFragNum = SWAP_BE32(((ufs_daddr_t *)indBlock)[indBlockOff]);
+ }
+
+ indBlock = ReadBlock(indFragNum, 0, gBlockSize, 0, 1);
+ indBlockOff = blockNum / refsPerBlock;
+ blockNum %= refsPerBlock;
+ indFragNum = SWAP_BE32(((ufs_daddr_t *)indBlock)[indBlockOff]);
+ }
+
+ indBlock = ReadBlock(indFragNum, 0, gBlockSize, 0, 1);
+ diskFragNum = SWAP_BE32(((ufs_daddr_t *)indBlock)[blockNum]);
+ }
+
+ buffer = ReadBlock(diskFragNum+fragNum, blockOffset, length, buffer, cache);
+
+ return buffer;
+}
+
+static long ReadFile( InodePtr fileInode, long * length )
+{
+ long bytesLeft, curSize, curFrag = 0;
+ char *buffer, *curAddr = (char *)kLoadAddr;
+
+#ifdef __i386__
+ curAddr = gFSLoadAddress;
+#endif
+
+ bytesLeft = *length = fileInode->di_size;
+
+ if (*length > kLoadSize) {
+ printf("File is too large.\n");
+ return -1;
+ }
+
+ while (bytesLeft) {
+ if (bytesLeft > gBlockSize) curSize = gBlockSize;
+ else curSize = bytesLeft;
+
+ buffer = ReadFileBlock(fileInode, curFrag, 0, curSize, curAddr, 0);
+ if (buffer == 0) break;
+
+ curFrag += gFragsPerBlock;
+ curAddr += curSize;
+ bytesLeft -= curSize;
+ }
+
+ return bytesLeft;
+}
* All rights reserved.
*/
-#include <bsd/sys/types.h>
-#include <bsd/sys/param.h>
-#include <bsd/sys/vnode.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/vnode.h>
#include <ufs/ufs/dir.h>
#include <architecture/byte_order.h>
#include "ufs_byteorder.h"
#ifndef __LIBSAIO_UFS_BYTEORDER_H
#define __LIBSAIO_UFS_BYTEORDER_H
-#include <bsd/sys/disktab.h>
-#include <bsd/sys/vnode.h>
-#include <bsd/sys/buf.h>
-#include <bsd/dev/disk.h>
-#include <bsd/ufs/ufs/quota.h>
-#include <bsd/ufs/ufs/inode.h>
-#include <bsd/ufs/ffs/fs.h>
+#include <sys/disktab.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+#include <dev/disk.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <ufs/ffs/fs.h>
void byte_swap_ints(int *array, int count);
void byte_swap_shorts(short *array, int count);
void byte_swap_partition(struct partition *part);
void byte_swap_dinode_in(struct dinode *di);
void byte_swap_dir_block_in(char *addr, int count);
+void byte_swap_inode_in(struct dinode *dc, struct dinode *ic);
#endif /* !__LIBSAIO_UFS_BYTEORDER_H */
* Copyright 1993 NeXT, Inc.
* All rights reserved.
*/
-#include "io_inline.h"
+
#include "libsaio.h"
-#include "vga.h"
#include "vbe.h"
-#include "kernBootStruct.h"
-#include "appleClut8.h"
-
-/*
- * Graphics mode settings.
- */
-BOOL in_linear_mode;
-unsigned char * frame_buffer;
-unsigned short screen_width;
-unsigned short screen_height;
-unsigned char bits_per_pixel;
-unsigned short screen_rowbytes;
/*
* Various inline routines for video I/O
outb (port + 1, (inb (port + 1) & ~clear) | set);
}
-/*
- * Local Prototypes
- */
-void setupPalette(VBEPalette * p, const unsigned char * g);
-
/*
* Globals
*/
static biosBuf_t bb;
-#if 0
-static char *models[] = { "Text",
- "CGA",
- "Hercules",
- "Planar",
- "Packed Pixel",
- "Non-Chain 4",
- "Direct Color",
- "YUV" };
-#endif
-
-int
-set_linear_video_mode(unsigned short mode)
-{
- VBEInfoBlock vinfo;
- VBEModeInfoBlock minfo;
- int err;
- VBEPalette palette;
-
- do {
- /*
- * See if VESA is around.
- */
- err = getVBEInfo(&vinfo);
- if (err != errSuccess)
- {
- printf("VESA not available.\n");
- break;
- }
-
-#if 0
- /*
- * See if this mode is supported.
- */
- err = getVBEModeInfo(mode, &minfo);
- if ( !((err == errSuccess) &&
- (minfo.ModeAttributes & maModeIsSupportedBit) &&
- (minfo.ModeAttributes & maGraphicsModeBit) /* &&
- (minfo.ModeAttributes & maLinearFrameBufferAvailBit)*/) )
- {
- printf("Mode %d is not supported.\n", mode);
- err = errFuncNotSupported;
- break;
- }
-#endif
-
- /*
- * Set the mode.
- */
- err = setVBEMode(mode | kLinearFrameBufferBit );
- if ( err != errSuccess )
- {
- if (vinfo.VESAVersion < MIN_VESA_VERSION)
- {
- printf("Video Card is VESA %d.%d. It must be at least VESA %d.%d\n",
- vinfo.VESAVersion >> 8,
- vinfo.VESAVersion & 0xff,
- MIN_VESA_VERSION >> 8,
- MIN_VESA_VERSION & 0xff);
- }
- else
- {
- printf("Error #%d in set video mode.\n", err);
- }
- break;
- }
-
- /*
- * Get mode info.
- */
- err = getVBEModeInfo(mode, &minfo);
- if ( err != errSuccess )
- {
- printf("Error #%d in get mode info.\n", err);
- break;
- }
-
- /*
- * Set the palette.
- */
- if (( vinfo.VESAVersion >= MIN_VESA_VERSION ) &&
- ( minfo.BitsPerPixel == 8 ))
- {
- setupPalette(&palette, appleClut8);
- if ((err = setVBEPalette(palette)) != errSuccess)
- {
- printf("Error #%d in setting palette.\n", err);
- break;
- }
- }
-
- err = errSuccess;
- in_linear_mode = YES;
- screen_width = minfo.XResolution;
- screen_height = minfo.YResolution;
- bits_per_pixel = minfo.BitsPerPixel;
- screen_rowbytes = minfo.BytesPerScanline;
-
- /* The S3 video card reports 15 bits... the video console driver
- * Can't deal.. set it to 16.
- */
- if (bits_per_pixel > 8 && bits_per_pixel < 16)
- bits_per_pixel = 16;
-
- frame_buffer = (unsigned char *) ADDRESS(minfo.PhysBasePtr_low,
- minfo.PhysBasePtr_1,
- minfo.PhysBasePtr_2,
- minfo.PhysBasePtr_high);
- }
- while ( 0 );
-
- return err;
-}
-
-void setupPalette(VBEPalette * p, const unsigned char * g)
+int getVBEInfo( void * infoBlock )
{
- int i;
- unsigned char * source = (unsigned char *) g;
-
- for (i = 0; i < 256; i++)
- {
- (*p)[i] = 0;
- (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
- (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
- (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
- }
-}
-
-int getVBEInfo(void *vinfo_p)
-{
- bb.intno = 0x10;
+ bb.intno = 0x10;
bb.eax.rr = funcGetControllerInfo;
- bb.es = SEG(vinfo_p);
- bb.edi.rr = OFF(vinfo_p);
- bios(&bb);
+ bb.es = SEG( infoBlock );
+ bb.edi.rr = OFF( infoBlock );
+ bios( &bb );
return(bb.eax.r.h);
}
-int getVBEModeInfo(int mode, void *minfo_p)
+int getVBEModeInfo( int mode, void * minfo_p )
{
- bb.intno = 0x10;
+ bb.intno = 0x10;
bb.eax.rr = funcGetModeInfo;
bb.ecx.rr = mode;
- bb.es = SEG(minfo_p);
+ bb.es = SEG(minfo_p);
bb.edi.rr = OFF(minfo_p);
bios(&bb);
return(bb.eax.r.h);
#ifndef __LIBSAIO_VBE_H
#define __LIBSAIO_VBE_H
-/*
- * Graphics mode settings.
- */
-extern BOOL in_linear_mode;
-extern unsigned char * frame_buffer;
-extern unsigned short screen_width;
-extern unsigned short screen_height;
-extern unsigned char bits_per_pixel;
-extern unsigned short screen_rowbytes;
-
#define MIN_VESA_VERSION 0x200
#define SEG(address) \
((unsigned short)(((unsigned long)address & 0xffff0000) >> 4))
-#define OFF(address) ((unsigned short)((unsigned long)address & 0x0000ffff))
-#define RTOV(low, one, two, high) \
- (((unsigned long)high << 12) | ((unsigned long)one << 8) | \
- (unsigned long)low)
-#define ADDRESS(low, one, two, high) \
- (((unsigned long)high << 24) | ((unsigned long)two << 16) | \
- ((unsigned long)one << 8) | (unsigned long)low)
+
+#define OFF(address) \
+ ((unsigned short)((unsigned long)address & 0x0000ffff))
+
+#define VBEMakeUInt32(x) \
+ (((unsigned long)x##_high << 24) | \
+ ((unsigned long)x##_2 << 16) | \
+ ((unsigned long)x##_1 << 8) | \
+ (unsigned long)x##_low)
+
+#define VBEDecodeFP(t, fp) \
+ ((t)(((fp ## _low) | ((fp ## _1 ) << 8)) + \
+ (((fp ## _2) << 4) | ((fp ## _high ) << 12))))
/*
- * Functions
+ * Functions
*/
enum {
funcGetControllerInfo = 0x4F00,
* Capabilites
*/
enum {
- capDACWidthIsSwitchableBit = (1 << 0), /* 1 = yes; 0 = no */
- capControllerIsNotVGACompatableBit = (1 << 1), /* 1 = no; 0 = yes */
- capOldRAMDAC = (1 << 2) /* 1 = yes; 0 = no */
+ capDACWidthIsSwitchableBit = (1 << 0), /* 1 = yes; 0 = no */
+ capControllerIsNotVGACompatableBit = (1 << 1), /* 1 = no; 0 = yes */
+ capOldRAMDAC = (1 << 2) /* 1 = yes; 0 = no */
};
/*
};
/*
- * Modes
+ * Modes
*/
enum {
mode640x400x256 = 0x100,
mode1280x1024x555 = 0x119,
mode1280x1024x565 = 0x11A,
mode1280x1024x888 = 0x11B,
- modeSpecial = 0x81FF
+ modeSpecial = 0x81FF,
+ modeEndOfList = 0xFFFF
};
/*
- * Get/Set VBE Mode parameters
+ * Get/Set VBE Mode parameters
*/
enum {
kLinearFrameBufferBit = (1 << 14),
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1993 NeXT, Inc.
- * All rights reserved.
- */
-#include "io_inline.h"
-#include "libsaio.h"
-#include "vga.h"
-
-#define VGA_SEQ_CNT 5
-#define VGA_CRT_CNT 25
-#define VGA_ATR_CNT 21
-#define VGA_GFX_CNT 9
-
-typedef struct VGAState {
- /* Miscellaneous output register. */
- unsigned char miscOutput;
- /* Sequencer registers. */
- unsigned char sequencerData[VGA_SEQ_CNT];
- /* CRT Controller registers. */
- unsigned char crtcData[VGA_CRT_CNT];
- /* Graphics controller registers. */
- unsigned char graphicsData[VGA_GFX_CNT];
- /* Attribute controller registers. */
- unsigned char attrData[VGA_ATR_CNT];
-} VGAState;
-
-#if 0
-/* VGA Mode 0x03. */
-
-static const VGAState VGAMode3 = {
- /* Miscellaneous output register. */
- 0x67,
- /* Sequencer registers. */
- { 0x01, 0x00, 0x03, 0x00, 0x02 },
- /* CRT controller registers. */
- {
- 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f,
- 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x8e, 0x8f, 0x28,
- 0x1f, 0x96, 0xb9, 0xa3, 0xff,
- },
- /* Graphics controller registers. */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff },
- /* Attribute controller registers. */
- {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39,
- 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08,
- 0x00,
- },
-};
-#endif
-
-/* VGA Mode 0x12. */
-
-static const VGAState VGAMode12 = {
- /* Miscellaneous output register. */
- 0xe3,
- /* Sequencer registers. */
- {0x03, 0x21, 0x0f, 0x00, 0x06},
- /* CRT controller registers. */
- {
- 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xea, 0x8c,
- 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 0xff,
- },
- /* Graphics controller registers. */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff },
- /* Attribute controller registers. */
- {
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03,
- 0x01, 0x00,
- 0x03, 0x00,
- 0x00,
- },
-};
-
-#define palette_entry(r,g,b) (((r) << 4)|((g) << 2)|(b))
-
-static const unsigned char colorData[4] = {
- 0x00, 0x15, 0x2a, 0x3f,
-};
-
-#ifdef NOTYET
-static const unsigned char mode_03_palette[] = {
- palette_entry(0, 0, 0),
- palette_entry(0, 0, 2),
- palette_entry(0, 2, 0),
- palette_entry(0, 2, 2),
- palette_entry(2, 0, 0),
- palette_entry(2, 0, 2),
- palette_entry(2, 2, 0),
- palette_entry(2, 2, 2),
- palette_entry(0, 0, 1),
- palette_entry(0, 0, 3),
- palette_entry(0, 2, 1),
- palette_entry(0, 2, 3),
- palette_entry(2, 0, 1),
- palette_entry(2, 0, 3),
- palette_entry(2, 2, 1),
- palette_entry(2, 2, 3),
- palette_entry(0, 1, 0),
- palette_entry(0, 1, 2),
- palette_entry(0, 3, 0),
- palette_entry(0, 3, 2),
- palette_entry(2, 1, 0),
- palette_entry(2, 1, 2),
- palette_entry(2, 3, 0),
- palette_entry(2, 3, 2),
- palette_entry(0, 1, 1),
- palette_entry(0, 1, 3),
- palette_entry(0, 3, 1),
- palette_entry(0, 3, 3),
- palette_entry(2, 1, 1),
- palette_entry(2, 1, 3),
- palette_entry(2, 3, 1),
- palette_entry(2, 3, 3),
- palette_entry(1, 0, 0),
- palette_entry(1, 0, 2),
- palette_entry(1, 2, 0),
- palette_entry(1, 2, 2),
- palette_entry(3, 0, 0),
- palette_entry(3, 0, 2),
- palette_entry(3, 2, 0),
- palette_entry(3, 2, 2),
- palette_entry(1, 0, 1),
- palette_entry(1, 0, 3),
- palette_entry(1, 2, 1),
- palette_entry(1, 2, 3),
- palette_entry(3, 0, 1),
- palette_entry(3, 0, 3),
- palette_entry(3, 2, 1),
- palette_entry(3, 2, 3),
- palette_entry(1, 1, 0),
- palette_entry(1, 1, 2),
- palette_entry(1, 3, 0),
- palette_entry(1, 3, 2),
- palette_entry(3, 1, 0),
- palette_entry(3, 1, 2),
- palette_entry(3, 3, 0),
- palette_entry(3, 3, 2),
- palette_entry(1, 1, 1),
- palette_entry(1, 1, 3),
- palette_entry(1, 3, 1),
- palette_entry(1, 3, 3),
- palette_entry(3, 1, 1),
- palette_entry(3, 1, 3),
- palette_entry(3, 3, 1),
- palette_entry(3, 3, 3),
-};
-#endif NOTYET
-
-static void
-spin(volatile int count)
-{
- while (count--)
- count = count;
-}
-
-void
-set_video_mode(unsigned int mode)
-{
- register unsigned int j, k;
- const VGAState * state;
- extern unsigned short screen_width;
- extern unsigned short screen_height;
-
- screen_width = 640;
- screen_height = 480;
-
- switch (mode) {
- case 0x02:
- case 0x03:
- video_mode(mode);
- return;
- /*
- state = &VGAMode3;
- break;
- */
- case 0x12:
- state = &VGAMode12;
- break;
- default:
- return;
- }
-
- /* Turn the video off while we are doing this.... */
- outb(VGA_SEQ_INDEX, 1);
- outb(VGA_SEQ_DATA, state->sequencerData[1]);
-
- /* Set the attribute flip-flop to "index" */
- inb(VGA_INPUT_STATUS_1);
-
- /* Give palette to CPU, turns off video */
- outb(VGA_WRITE_ATTR_INDEX, 0x00);
-
- /* Set the general registers */
- outb(VGA_WRITE_MISC_PORT, state->miscOutput);
- outb(VGA_WRITE_FEATURE_PORT, 0x00);
-
- /* Load the sequencer registers */
- for (k = 0; k < VGA_SEQ_CNT; k++) {
- outb(VGA_SEQ_INDEX, k);
- outb(VGA_SEQ_DATA, state->sequencerData[k]);
- }
- outb(VGA_SEQ_INDEX, 0x00);
- outb(VGA_SEQ_DATA, 0x03); /* Low order two bits are reset bits */
-
- /* Load the CRTC registers.
- * CRTC registers 0-7 are locked by a bit in register 0x11. We need
- * to unlock these registers before we can start setting them.
- */
- outb(VGA_CRTC_INDEX, 0x11);
- outb(VGA_CRTC_DATA, 0x00); /* Unlocks registers 0-7 */
- for (k = 0; k < VGA_CRT_CNT; k++) {
- outb(VGA_CRTC_INDEX, k);
- outb(VGA_CRTC_DATA, state->crtcData[k]);
- }
-
- /* Load the attribute registers */
- inb(VGA_INPUT_STATUS_1); /* Set the attribute flip-flop to "index" */
- for (k = 0; k < VGA_ATR_CNT; k++) {
- outb(VGA_WRITE_ATTR_INDEX, k);
- outb(VGA_WRITE_ATTR_DATA, state->attrData[k]);
- }
-
- /* Load graphics registers */
- for (k = 0; k < VGA_GFX_CNT; k++) {
- outb(VGA_GFX_INDEX, k);
- outb(VGA_GFX_DATA, state->graphicsData[k]);
- }
-
- /* Set up the palette. */
-
- outb(VGA_PALETTE_WRITE, 0);
- for (k = 0; k < 256; k++) {
-#ifdef NOTYET
- if (mode == 0x12) {
-#endif NOTYET
- j = colorData[k % 4];
- outb(VGA_PALETTE_DATA, j); spin(1000);
- outb(VGA_PALETTE_DATA, j); spin(1000);
- outb(VGA_PALETTE_DATA, j); spin(1000);
-#ifdef NOTYET
- } else {
- j = mode_03_palette[(k - 64) % 64];
- outb(VGA_PALETTE_DATA, colorData[(j >> 4) & 3]);
- outb(VGA_PALETTE_DATA, colorData[(j >> 2) & 3]);
- outb(VGA_PALETTE_DATA, colorData[j & 3]);
- }
-#endif NOTYET
- }
-
- /* Re-enable video */
- /* First, clear memory to zeros */
- bzero((void *) VGA_BUF_ADDR, VGA_BUF_LENGTH);
-
- /* Set the attribute flip-flop to "index" */
- inb(VGA_INPUT_STATUS_1);
-
- /* Give the palette back to the VGA */
- outb(VGA_WRITE_ATTR_INDEX, 0x20);
-
- // Really re-enable video.
- outb(VGA_SEQ_INDEX, 1);
- outb(VGA_SEQ_DATA, (state->sequencerData[1] & ~0x20));
-}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * VGA Graphics Controller Port
- */
-
-#ifndef __LIBSAIO_VGA_H
-#define __LIBSAIO_VGA_H
-
-#define VGA_BUF_ADDR 0xA0000
-#define VGA_BUF_LENGTH 0x10000
-
-#define VGA_GFX_INDEX 0x3CE
-#define VGA_GFX_DATA 0x3CF
-#define VGA_GFX_RD_MAP_SEL 0x4
-#define VGA_GFX_BIT_MASK 0x8
-#define VGA_NUM_GFX_REGS 6 // number of graphics controller
- // registers to preserve
-#define VGA_SEQ_INDEX 0x3C4
-#define VGA_SEQ_DATA 0x3C5
-#define VGA_SEQ_MAP_MASK 0x2
-#define VGA_NUM_SEQ_REGS 5 // number of sequencer
- // registers to preserve
-#define VGA_AC_ADDR 0x3C0
-#define VGA_NUM_AC_REGS 0x14
-
-#define VGA_CRTC_INDEX 0x3D4
-#define VGA_CRTC_DATA 0x3D5
-
-#define VGA_READ_ATTR_INDEX 0x3C1
-#define VGA_READ_ATTR_DATA 0x3C1
-#define VGA_WRITE_ATTR_INDEX 0x3C0
-#define VGA_WRITE_ATTR_DATA 0x3C0
-
-#define VGA_PALETTE_WRITE 0x3C8
-#define VGA_PALETTE_READ 0x3C7
-#define VGA_PALETTE_DATA 0x3C9
-
-#define VGA_INPUT_STATUS_1 0x3DA
-#define VGA_READ_MISC_PORT 0x3CC
-#define VGA_WRITE_MISC_PORT 0x3C2
-
-#define VGA_READ_FEATURE_PORT 0x3CA
-#define VGA_WRITE_FEATURE_PORT 0x3DA
-
-#endif /* !__LIBSAIO_VGA_H */
INSTALLDIR = $(SYMROOT)
OPTIM = -O2
-CFLAGS = $(OPTIM) -g -Wall -traditional-cpp
+CFLAGS = $(OPTIM) -g -Wmost -Werror
DEFINES=
INC = -I.
ifneq "" "$(wildcard /bin/mkdirs)"
return NULL;
if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
- if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
+ if (b==-1 && i!=-1) b ^= i, i ^= b, b ^= i; /* swap them round */
if ((b==R_SI || b==R_DI) && i!=-1)
- b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
+ b ^= i, i ^= b, b ^= i; /* have BX/BP as base, SI/DI index */
if (b==i) return NULL;/* shouldn't ever happen, in theory */
if (i!=-1 && b!=-1 &&
(i==R_BP || i==R_BX || b==R_SI || b==R_DI))
INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone
OPTIM = -Os
-CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Wno-precomp \
- -munaligned-text -static -traditional-cpp
+CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost -Werror \
+ -fno-builtin -static
DEFINES=
CONFIG = hd
INC = -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR)
)
/* Returns actual number of bytes emitted as compressed stream 'out.' */
{
- unsigned int c, ct, j, jmatch, jabove, match;
- unsigned int data[32], version;
- unsigned int word, token, tokenct, total;
+ unsigned int c, ct, j, jmatch = 0, jabove, match;
+ unsigned int data[32];
+ unsigned int word, token, tokenct;
unsigned char *outorigin = out;
/* First, put version number into stream. */
unsigned int c, j, k, jmatch, jabove;
unsigned int length, even_length, word, token, version;
unsigned char *outorigin = out;
- int *a, *b;
version = *in++;
version = (version<<8) | (*in++);
LANGDIR = $(INSTALLDIR)/English.lproj
OPTIM = -Os
-CFLAGS = $(RC_CFLAGS) $(OPTIM) -Wmost -Wno-precomp -g -I../rcz -traditional-cpp -nostdinc -nostdlib -I/usr/include -I/System/Library/Frameworks/System.framework/Headers
-LDFLAGS = /usr/lib/crt1.o /System/Library/Frameworks/System.framework/System -lcc
+CFLAGS = $(RC_CFLAGS) $(OPTIM) -Wmost -Werror -g -I../rcz -nostdinc -nostdlib -I/usr/include \
+ -I/System/Library/Frameworks/System.framework/Headers
+LDFLAGS = -L/usr/lib -lcrt1.o -lSystem -lcc_dynamic
CFILES = machOconv.c mkfont.c tif_packbits.c
MFILES = dumptiff.m
HFILES = cursor.h
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef lint
-static char rcsid[] = "$Header: /cvs/Darwin/System/boot/i386/util/tif_packbits.c,v 1.1.1.2 1999/08/04 21:17:19 wsanchez Exp $";
+static char rcsid[] = "$Header: /cvs/Darwin/boot/i386/util/tif_packbits.c,v 1.1.1.2 1999/08/04 21:17:19 wsanchez Exp $";
#endif
/*