1 ; boot1.asm - boot1 written for turbo assembler, since gas only
2 ; generates 32 bit code and this must run in real mode.
3 ; To compile as hard disk boot1:
4 ; tasm /m3 /dBOOTDEV=HDISK boot1
8 ; To compile as floppy boot1f:
9 ; tasm /m3 /dBOOTDEV=FLOPPY boot1 ,boot1f
12 ; ren boot1f.bin boot1f
14 ;***********************************************************************
15 ; This is the code for the NeXT boot1 bootsector.
16 ;***********************************************************************
18 P486 ;enable i386 instructions
21 ASSUME CS:CSEG,DS:CSEG
25 ;BOOTSEG = 100h ; boot will be loaded at 4k
29 BUFSZ = 2000h ; 8K disk transfer buffer
31 ; FDISK partition table in sector 0
32 PARTSTART = 1beh ; starting address of partition table
33 NUMPART = 4 ; number of partitions in partition table
34 PARTSZ = 16 ; each partition table entry is 16 bytes
35 BOOT_IND = 0 ; offset of boot indicator in partition table
36 BEG_HEAD = 1 ; offset of beginning head
37 BEG_SEC = 2 ; offset of beginning sector
38 BEG_CYL = 3 ; offset of beginning cylinder
39 NAME_OFFSET = 4 ; offset of partition name
40 PARTSEC = 8 ; offset of partition sector specifier
41 NEXTNAME = 0A7h ; value of boot_ind, means bootable partition
43 LOADSZ = 88 ; maxiumum possible size of unix boot
- 44k
48 ;BOOTDEV = ? ; set to 00h for floppy, 80h for hard disk
49 ; (use a command line switch to set)
52 DISKLABEL = 15 ; sector num of 2nd disk label, 1st is trashed by bootsec
55 ; We support disk label version 3 "3Vld" in our little endian world
62 ; This code is a replacement for boot1. It is loaded at 0x0:0x7c00
67 mov ss,ax ; set up stack seg
69 sti ; reenable interrupts
75 cld ; so pointers will get updated
76 mov di,0E000h ; relocate boot program to 0xE000
77 mov cx,100h ; copy 256x2 bytes
79 off1 = 0E000h + (a1 - start)
80 jmp FAR 0000:off1 ; jump to a1 in relocated place
88 ; load the boot loader (boot2) into BOOTSEG:BUFSZ
91 ; ljmp to the second stage boot loader (boot2).
92 ; After ljmp, cs is BOOTSEG and boot1 (BUFSZ bytes) will be used
93 ; as an internal buffer "intbuf".
95 xor edx,edx ; bootdev = 0 for hard disk
96 IF ( BOOTDEV EQ FLOPPY )
97 inc edx ; bootdev = 1 for floppy disk
100 ;boot2 immediately follows disk buffer; 4K + BUFSZ
101 jmp FAR BOOTSEG:(BOOTOFF + BUFSZ)
102 ; jump to boot2 in loaded location
108 call message ; display intro message
110 ; load second stage boot from fixed disk
111 ; get boot drive parameters
112 ; Note: I believe that the bootsector read may not be necessary;
113 ; at least some blk0 bootsectors leave a pointer to the active
114 ; partition entry in si (assuming there was another blk0 bootsec)
118 IF ( BOOTDEV EQ HDISK )
120 ; read sector 0 into BOOTSEG:0 by using BIOS call (INT 13H 02H)
121 ; this gets info on the disk's actual partition table
122 ; However, in the case of multiple partitions, this may not
123 ; be the same as the sector with the code here.
125 mov di,5 ; try 5 times to read bootsector
128 xor bx, bx ; buffer is BOOTSEG:0
132 mov bx,BOOTOFF ; actually, it's 0:BOOTOFF
133 inc cx ; cyl 0, sector 1
134 mov dl,BOOTDEV ; target 0, head 0
137 int 13h ; read the bootsector
142 ; woops, bios failed to read sector
148 jmp read_error ; disk failed
151 read_success1: ; find the NeXT partition
156 mov al, [es:(bx+BOOTOFF)+NAME_OFFSET]
158 cmp al, NEXTNAME ; is it NeXT partition?
159 jne cont ; nope, keep looking
161 foundNextPart: ; found it, get label location
163 mov eax, [es:(bx+BOOTOFF)+PARTSEC]
164 ; offset to NeXT partition
165 add eax, DISKLABEL ; add offset to the label
166 jmp getLabl ; fetch that label
170 loop again ; if more part table entries,
173 ; fall through, didn't find NeXT disk partition entry
177 ; Read NeXT disk label
178 mov eax, DISKLABEL ; Get block number of label
180 mov bx,BOOTOFF ; read into load area
184 ; we used to think about testing the disk label version here...
186 mov bx,BOOTOFF ; point to beginning of label
188 ; Use values from label to read entire boot program
189 ; Get block number of boot
190 ; Get dl_secsize and dl_boot0_blkno[0]
191 mov edx, [es:(bx + DL_DISKTAB+DT_SECSIZE)]
192 bswap edx ; edx -> sector size
194 mov eax, [es:(bx + DL_DISKTAB+DT_BOOT0_BLKNO)]
195 bswap eax ; eax -> block #
197 ; Compute dl_secsize * dt_boot0_blkno[0] / 512
198 shr edx, 9 ; divide dl_secsize by 512
199 mul edx ; multiply boot block loc
202 mov bx, (BUFSZ + BOOTOFF) ; read boot2 into BOOTSEG:BUFSZ
203 mov edi, LOADSZ ; read this many sectors
205 push eax ; push sector #
206 push bx ; push buffer address
207 mov ecx, edi ; max number of sectors to read
212 add eax, ecx ; add number of sectors read
214 shl cx, 9 ; multiply by 512 bytes per sector
222 spt: DW 0 ; sectors;track (one-based)
223 spc: DW 0 ; tracks;cylinder (zero-based)
224 nsec: DW 0 ; number of sectors to read
226 readSectors: ; eax has starting block #, bx has offset from BOOTSEG
227 ; cx has maximum number of sectors to read
228 ; Trashes ax, bx, cx, dx
230 ; BIOS call "INT 0x13 Function 0x2" to read sectors
231 ; ah = 0x2 al = number of sectors
232 ; ch = cylinder cl = sector
233 ; dh = head dl = drive (0x80=hard disk, 0=floppy disk)
234 ; es:bx = segment:offset of buffer
236 IF ( BOOTDEV EQ FLOPPY )
243 push bx ; save offset
246 mov ebx, eax ; bx -> block #
248 mov cx, [WORD spc] ; cx -> sectors/cyl
250 xor edx,edx ; prepare for division
251 div ecx ; eax = cyl, edx=remainder
252 push ax ; save cylinder #, sec/spc
255 mov cx, [WORD spt] ; ecx -> sectors/track
256 xor edx,edx ; prepare for division
258 push ax ; save head, (secspc)/spt
260 mov eax, ebx ; reload block #
261 xor edx, edx ; prepare for division
262 div ecx ; edx has sector #
264 sub cx, dx ;cx now has number of sectors to read
266 jge last ; use the minimum of bx and cx
270 mov cx, dx ; cl -> sector
273 mov dh, al ; dh -> head
276 mov ch, al ; ch -> cyl
277 mov dl, BOOTDEV ; floppy disk
281 or cl,al ; retain pesky big cyl bits
283 ; mov al, 1 ; get # of sectors
284 ;pop ax ; number of sectors to read
287 mov ah, 2 ; bios read function
292 mov cx, [WORD nsec] ; return number of sectors read
296 getinfo: ; get some drive parameters
297 mov dl, BOOTDEV ; boot drive is drive C
303 mov al, dh ; max head #
304 inc al ; al -> tracks/cyl
305 and cx, 3fh ; cl -> secs/track
306 mul cl ; ax -> secs/cyl
313 message: ; write the error message in ds:esi
319 mov bx, 1 ; bh=0, bl=1 (blue)
323 lodsb ; load a byte into al
326 mov ah, 0eh ; bios int 10, function 0xe
327 int 10h ; bios display a byte in tty mode
334 mov bx, 1 ; bh=0, bl=1 (blue)
335 mov ah, 0eh ; bios int 10, function 0xe
336 int 10h ; bios display a byte in tty mode
341 hexout:
; print ebx as hex number
344 mov cx,8 ;output 8 nibbles
372 boot_exit: ; boot_exit: write error message and halt
373 call message ; display error message
377 intro: db 10,'NEXTSTEP boot1 vXX.XX.XX.XX.XX',10,13,0
378 eread: db 'Read error',10,13,0
380 ; the last 2 bytes in the sector contain the signature
382 a2 = 510 - (d1 - start)