]> git.saurik.com Git - apple/boot.git/blob - i386/boot1/boot1.asm
boot-80.1.tar.gz
[apple/boot.git] / i386 / boot1 / boot1.asm
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
5 ; tlink boot1
6 ; exe2bin boot1
7 ; ren boot1.bin boot1
8 ; To compile as floppy boot1f:
9 ; tasm /m3 /dBOOTDEV=FLOPPY boot1 ,boot1f
10 ; tlink boot1f
11 ; exe2bin boot1f
12 ; ren boot1f.bin boot1f
13
14 ;***********************************************************************
15 ; This is the code for the NeXT boot1 bootsector.
16 ;***********************************************************************
17
18 P486 ;enable i386 instructions
19 IDEAL
20 SEGMENT CSEG
21 ASSUME CS:CSEG,DS:CSEG
22
23 SDEBUG = 0
24
25 ;BOOTSEG = 100h ; boot will be loaded at 4k
26 ;BOOTOFF = 0000h
27 BOOTSEG = 00h
28 BOOTOFF = 1000h
29 BUFSZ = 2000h ; 8K disk transfer buffer
30
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
42
43 LOADSZ = 88 ; maxiumum possible size of unix boot - 44k
44
45 FLOPPY = 0
46 HDISK = 80h
47
48 ;BOOTDEV = ? ; set to 00h for floppy, 80h for hard disk
49 ; (use a command line switch to set)
50
51 ; NeXT disk label
52 DISKLABEL = 15 ; sector num of 2nd disk label, 1st is trashed by bootsec
53 DL_DISKTAB = 44
54
55 ; We support disk label version 3 "3Vld" in our little endian world
56 DL_V3 = 33566c64h
57
58 ; NeXT disktab
59 DT_SECSIZE = 48
60 DT_BOOT0_BLKNO = 80
61
62 ; This code is a replacement for boot1. It is loaded at 0x0:0x7c00
63
64 start:
65 mov ax,BOOTSEG
66 cli ; interrupts off
67 mov ss,ax ; set up stack seg
68 mov sp,0fff0h
69 sti ; reenable interrupts
70
71 xor ax,ax
72 mov es,ax
73 mov ds,ax
74 mov si,7C00h
75 cld ; so pointers will get updated
76 mov di,0E000h ; relocate boot program to 0xE000
77 mov cx,100h ; copy 256x2 bytes
78 repnz movsw ; move it
79 off1 = 0E000h + (a1 - start)
80 jmp FAR 0000:off1 ; jump to a1 in relocated place
81
82 a1:
83 mov ax,0E00h
84 mov ds,ax
85 mov ax,BOOTSEG
86 mov es,ax
87
88 ; load the boot loader (boot2) into BOOTSEG:BUFSZ
89 call loadboot
90
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".
94
95 xor edx,edx ; bootdev = 0 for hard disk
96 IF ( BOOTDEV EQ FLOPPY )
97 inc edx ; bootdev = 1 for floppy disk
98 ENDIF
99
100 ;boot2 immediately follows disk buffer; 4K + BUFSZ
101 jmp FAR BOOTSEG:(BOOTOFF + BUFSZ)
102 ; jump to boot2 in loaded location
103
104
105
106 loadboot:
107 mov si, OFFSET intro
108 call message ; display intro message
109
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)
115
116 call getinfo
117
118 IF ( BOOTDEV EQ HDISK )
119
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.
124
125 mov di,5 ; try 5 times to read bootsector
126
127 retry_disk:
128 xor bx, bx ; buffer is BOOTSEG:0
129 mov ax,201h
130 mov cx,bx
131 mov dx,bx
132 mov bx,BOOTOFF ; actually, it's 0:BOOTOFF
133 inc cx ; cyl 0, sector 1
134 mov dl,BOOTDEV ; target 0, head 0
135
136 push di
137 int 13h ; read the bootsector
138 pop di
139
140 jnb read_success1
141
142 ; woops, bios failed to read sector
143 xor ax,ax
144 int 13h ; reset disk
145 dec di
146 jne retry_disk
147
148 jmp read_error ; disk failed
149
150
151 read_success1: ; find the NeXT partition
152 mov bx,PARTSTART
153 mov cx,NUMPART
154
155 again:
156 mov al, [es:(bx+BOOTOFF)+NAME_OFFSET]
157 ; get partition name
158 cmp al, NEXTNAME ; is it NeXT partition?
159 jne cont ; nope, keep looking
160
161 foundNextPart: ; found it, get label location
162
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
167
168 cont:
169 add bx, PARTSZ
170 loop again ; if more part table entries,
171 ; keep looking
172
173 ; fall through, didn't find NeXT disk partition entry
174
175 no_fdisk:
176 ENDIF
177 ; Read NeXT disk label
178 mov eax, DISKLABEL ; Get block number of label
179 getLabl:
180 mov bx,BOOTOFF ; read into load area
181 mov cx,1
182 call readSectors
183
184 ; we used to think about testing the disk label version here...
185
186 mov bx,BOOTOFF ; point to beginning of label
187
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
193
194 mov eax, [es:(bx + DL_DISKTAB+DT_BOOT0_BLKNO)]
195 bswap eax ; eax -> block #
196
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
200 ; by dl_secsize/512
201 ; eax has secno
202 mov bx, (BUFSZ + BOOTOFF) ; read boot2 into BOOTSEG:BUFSZ
203 mov edi, LOADSZ ; read this many sectors
204 nexsec:
205 push eax ; push sector #
206 push bx ; push buffer address
207 mov ecx, edi ; max number of sectors to read
208
209 call readSectors
210 pop bx
211 pop eax
212 add eax, ecx ; add number of sectors read
213 sub di, cx
214 shl cx, 9 ; multiply by 512 bytes per sector
215 add bx, cx
216
217 cmp di, 0
218 jne nexsec
219
220 ret
221
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
225
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
229
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
235
236 IF ( BOOTDEV EQ FLOPPY )
237 push eax
238 mov al,'.'
239 call putchr
240 pop eax
241 ENDIF
242
243 push bx ; save offset
244 mov [WORD nsec], cx
245
246 mov ebx, eax ; bx -> block #
247 xor ecx, ecx
248 mov cx, [WORD spc] ; cx -> sectors/cyl
249
250 xor edx,edx ; prepare for division
251 div ecx ; eax = cyl, edx=remainder
252 push ax ; save cylinder #, sec/spc
253
254 mov eax, edx
255 mov cx, [WORD spt] ; ecx -> sectors/track
256 xor edx,edx ; prepare for division
257 div ecx ; eax = head
258 push ax ; save head, (secspc)/spt
259
260 mov eax, ebx ; reload block #
261 xor edx, edx ; prepare for division
262 div ecx ; edx has sector #
263
264 sub cx, dx ;cx now has number of sectors to read
265 cmp cx, [WORD nsec]
266 jge last ; use the minimum of bx and cx
267 mov [WORD nsec], cx
268 last:
269
270 mov cx, dx ; cl -> sector
271 inc cl ; starts @ 1
272 pop ax ; get head
273 mov dh, al ; dh -> head
274
275 pop ax ; get cyl
276 mov ch, al ; ch -> cyl
277 mov dl, BOOTDEV ; floppy disk
278
279 xor al,al
280 shr ax,2
281 or cl,al ; retain pesky big cyl bits
282
283 ; mov al, 1 ; get # of sectors
284 ;pop ax ; number of sectors to read
285 mov ax, [WORD nsec]
286 pop bx ; get buffer
287 mov ah, 2 ; bios read function
288
289 int 13h
290
291 jb read_error
292 mov cx, [WORD nsec] ; return number of sectors read
293 ret
294
295
296 getinfo: ; get some drive parameters
297 mov dl, BOOTDEV ; boot drive is drive C
298 mov ah, 8h
299 push es
300 int 13h
301 pop es
302
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
307 mov [WORD spc], ax
308 mov [WORD spt], cx
309
310 ret
311
312
313 message: ; write the error message in ds:esi
314 ; to console
315 push es
316 mov ax,ds
317 mov es,ax
318
319 mov bx, 1 ; bh=0, bl=1 (blue)
320 cld
321
322 nextb:
323 lodsb ; load a byte into al
324 cmp al, 0
325 je done
326 mov ah, 0eh ; bios int 10, function 0xe
327 int 10h ; bios display a byte in tty mode
328 jmp nextb
329 done: pop es
330 ret
331
332 putchr:
333 push bx
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
337 pop bx
338 ret
339
340 IF SDEBUG
341 hexout: ; print ebx as hex number
342 push cx
343 push ax
344 mov cx,8 ;output 8 nibbles
345
346 htop:
347 rol ebx,4
348 mov al,bl
349 and al,0fh
350 cmp al,0ah
351 jb o_digit
352 add al,'A'-10
353 jmp o_print
354 o_digit: add al,'0'
355 o_print: call putchr
356 dec cx
357 jne htop
358 ; mov al,10
359 ; call putchr
360 ; mov al,13
361 ; call putchr
362 mov al,' '
363 call putchr
364 pop ax
365 pop cx
366 ret
367 ENDIF
368
369
370 read_error:
371 mov si, OFFSET eread
372 boot_exit: ; boot_exit: write error message and halt
373 call message ; display error message
374 halt: jmp halt
375
376
377 intro: db 10,'NEXTSTEP boot1 vXX.XX.XX.XX.XX',10,13,0
378 eread: db 'Read error',10,13,0
379
380 ; the last 2 bytes in the sector contain the signature
381 d1:
382 a2 = 510 - (d1 - start)
383 DB a2 dup (0)
384 DW 0AA55h
385 ENDS
386 END