]> git.saurik.com Git - apple/boot.git/blame - i386/boot1/boot1.asm
boot-111.1.tar.gz
[apple/boot.git] / i386 / boot1 / boot1.asm
CommitLineData
14c7c974
A
1; boot1.asm - boot1 written for turbo assembler, since gas only\r
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\r
14;***********************************************************************\r
15; This is the code for the NeXT boot1 bootsector.
16;***********************************************************************\r
17\r
18 P486 ;enable i386 instructions\r
19 IDEAL\r
20 SEGMENT CSEG\r
21 ASSUME CS:CSEG,DS:CSEG\r
22\r
23 SDEBUG = 0\r
24\r
25;BOOTSEG = 100h ; boot will be loaded at 4k\r
26;BOOTOFF = 0000h
27BOOTSEG = 00h
28BOOTOFF = 1000h
29BUFSZ = 2000h ; 8K disk transfer buffer\r
30\r
31; FDISK partition table in sector 0\r
32PARTSTART = 1beh ; starting address of partition table\r
33NUMPART = 4 ; number of partitions in partition table\r
34PARTSZ = 16 ; each partition table entry is 16 bytes\r
35BOOT_IND = 0 ; offset of boot indicator in partition table\r
36BEG_HEAD = 1 ; offset of beginning head\r
37BEG_SEC = 2 ; offset of beginning sector\r
38BEG_CYL = 3 ; offset of beginning cylinder\r
39NAME_OFFSET = 4 ; offset of partition name\r
40PARTSEC = 8 ; offset of partition sector specifier\r
41NEXTNAME = 0A7h ; value of boot_ind, means bootable partition\r
42\r
43LOADSZ = 88 ; maxiumum possible size of unix boot\r- 44k
44\r
45FLOPPY = 0
46HDISK = 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\r
52DISKLABEL = 15 ; sector num of 2nd disk label, 1st is trashed by bootsec\r
53DL_DISKTAB = 44\r
54\r
55; We support disk label version 3 "3Vld" in our little endian world\r
56DL_V3 = 33566c64h\r
57\r
58; NeXT disktab\r
59DT_SECSIZE = 48\r
60DT_BOOT0_BLKNO = 80\r
61\r\r
62; This code is a replacement for boot1. It is loaded at 0x0:0x7c00\r
63\r
64start:\r
65 mov ax,BOOTSEG
66 cli ; interrupts off\r
67 mov ss,ax ; set up stack seg\r
68 mov sp,0fff0h\r
69 sti ; reenable interrupts\r
70
71 xor ax,ax
72 mov es,ax
73 mov ds,ax
74 mov si,7C00h
75 cld ; so pointers will get updated\r
76 mov di,0E000h ; relocate boot program to 0xE000\r
77 mov cx,100h ; copy 256x2 bytes\r
78 repnz movsw ; move it\r
79 off1 = 0E000h + (a1 - start)\r
80 jmp FAR 0000:off1 ; jump to a1 in relocated place\r
81
82a1:\r
83 mov ax,0E00h\r
84 mov ds,ax\r
85 mov ax,BOOTSEG\r
86 mov es,ax\r
87\r
88 ; load the boot loader (boot2) into BOOTSEG:BUFSZ\r
89 call loadboot\r
90\r
91 ; ljmp to the second stage boot loader (boot2).\r
92 ; After ljmp, cs is BOOTSEG and boot1 (BUFSZ bytes) will be used\r
93 ; as an internal buffer "intbuf".\r
94\r
95 xor edx,edx ; bootdev = 0 for hard disk\r
96IF ( BOOTDEV EQ FLOPPY )
97 inc edx ; bootdev = 1 for floppy disk
98ENDIF
99
100 ;boot2 immediately follows disk buffer; 4K + BUFSZ\r
101 jmp FAR BOOTSEG:(BOOTOFF + BUFSZ)
102 ; jump to boot2 in loaded location\r
103\r
104\r
105\r
106loadboot:\r
107 mov si, OFFSET intro\r
108 call message ; display intro message\r
109\r
110 ; load second stage boot from fixed disk\r
111 ; get boot drive parameters\r
112 ; Note: I believe that the bootsector read may not be necessary;\r
113 ; at least some blk0 bootsectors leave a pointer to the active\r
114 ; partition entry in si (assuming there was another blk0 bootsec)\r
115\r
116 call getinfo\r
117\r
118IF ( BOOTDEV EQ HDISK )
119
120 ; read sector 0 into BOOTSEG:0 by using BIOS call (INT 13H 02H)\r
121 ; this gets info on the disk's actual partition table\r
122 ; However, in the case of multiple partitions, this may not\r
123 ; be the same as the sector with the code here.\r
124\r
125 mov di,5 ; try 5 times to read bootsector\r
126\r
127retry_disk:\r
128 xor bx, bx ; buffer is BOOTSEG:0\r
129 mov ax,201h\r
130 mov cx,bx\r
131 mov dx,bx\r
132 mov bx,BOOTOFF ; actually, it's 0:BOOTOFF
133 inc cx ; cyl 0, sector 1\r
134 mov dl,BOOTDEV ; target 0, head 0\r
135\r
136 push di\r
137 int 13h ; read the bootsector\r
138 pop di\r
139\r
140 jnb read_success1\r
141\r
142 ; woops, bios failed to read sector\r
143 xor ax,ax\r
144 int 13h ; reset disk\r
145 dec di\r
146 jne retry_disk\r
147\r
148 jmp read_error ; disk failed\r
149\r
150\r
151read_success1: ; find the NeXT partition\r
152 mov bx,PARTSTART\r
153 mov cx,NUMPART\r
154\r
155again:\r
156 mov al, [es:(bx+BOOTOFF)+NAME_OFFSET]
157 ; get partition name\r
158 cmp al, NEXTNAME ; is it NeXT partition?\r
159 jne cont ; nope, keep looking\r
160\r
161foundNextPart: ; found it, get label location\r
162\r
163 mov eax, [es:(bx+BOOTOFF)+PARTSEC]
164 ; offset to NeXT partition\r
165 add eax, DISKLABEL ; add offset to the label\r
166 jmp getLabl ; fetch that label\r
167\r
168cont:\r
169 add bx, PARTSZ\r
170 loop again ; if more part table entries,
171 ; keep looking\r
172\r
173 ; fall through, didn't find NeXT disk partition entry\r
174\r
175no_fdisk:\r
176ENDIF
177 ; Read NeXT disk label\r
178 mov eax, DISKLABEL ; Get block number of label\r
179getLabl:\r
180 mov bx,BOOTOFF ; read into load area
181 mov cx,1
182 call readSectors\r
183\r
184 ; we used to think about testing the disk label version here...\r
185
186 mov bx,BOOTOFF ; point to beginning of label
187\r
188 ; Use values from label to read entire boot program\r
189 ; Get block number of boot\r
190 ; Get dl_secsize and dl_boot0_blkno[0]\r
191 mov edx, [es:(bx + DL_DISKTAB+DT_SECSIZE)]\r
192 bswap edx ; edx -> sector size\r
193\r
194 mov eax, [es:(bx + DL_DISKTAB+DT_BOOT0_BLKNO)]\r
195 bswap eax ; eax -> block #\r
196
197 ; Compute dl_secsize * dt_boot0_blkno[0] / 512\r
198 shr edx, 9 ; divide dl_secsize by 512\r
199 mul edx ; multiply boot block loc
200 ; by dl_secsize/512\r
201 ; eax has secno\r
202 mov bx, (BUFSZ + BOOTOFF) ; read boot2 into BOOTSEG:BUFSZ\r
203 mov edi, LOADSZ ; read this many sectors\r
204nexsec:\r
205 push eax ; push sector #\r
206 push bx ; push buffer address\r
207 mov ecx, edi ; max number of sectors to read
208
209 call readSectors\r
210 pop bx\r
211 pop eax\r
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\r
219
220 ret\r
221\r
222spt: DW 0 ; sectors;track (one-based)\r
223spc: DW 0 ; tracks;cylinder (zero-based)\r
224nsec: DW 0 ; number of sectors to read
225\r
226readSectors: ; eax has starting block #, bx has offset from BOOTSEG\r
227 ; cx has maximum number of sectors to read
228 ; Trashes ax, bx, cx, dx\r
229\r
230 ; BIOS call "INT 0x13 Function 0x2" to read sectors\r
231 ; ah = 0x2 al = number of sectors\r
232 ; ch = cylinder cl = sector\r
233 ; dh = head dl = drive (0x80=hard disk, 0=floppy disk)\r
234 ; es:bx = segment:offset of buffer\r
235
236IF ( BOOTDEV EQ FLOPPY )
237 push eax\r
238 mov al,'.'\r
239 call putchr\r
240 pop eax\r
241ENDIF\r
242\r
243 push bx ; save offset\r
244 mov [WORD nsec], cx
245\r
246 mov ebx, eax ; bx -> block #\r
247 xor ecx, ecx\r
248 mov cx, [WORD spc] ; cx -> sectors/cyl\r
249\r
250 xor edx,edx ; prepare for division\r
251 div ecx ; eax = cyl, edx=remainder\r
252 push ax ; save cylinder #, sec/spc\r
253\r
254 mov eax, edx\r
255 mov cx, [WORD spt] ; ecx -> sectors/track\r
256 xor edx,edx ; prepare for division\r
257 div ecx ; eax = head\r
258 push ax ; save head, (secspc)/spt\r
259\r
260 mov eax, ebx ; reload block #\r
261 xor edx, edx ; prepare for division\r
262 div ecx ; edx has sector #\r
263\r
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
268last:
269
270 mov cx, dx ; cl -> sector\r
271 inc cl ; starts @ 1\r
272 pop ax ; get head\r
273 mov dh, al ; dh -> head\r
274\r
275 pop ax ; get cyl\r
276 mov ch, al ; ch -> cyl\r
277 mov dl, BOOTDEV ; floppy disk\r
278\r
279 xor al,al\r
280 shr ax,2\r
281 or cl,al ; retain pesky big cyl bits\r
282
283; mov al, 1 ; get # of sectors\r
284;pop ax ; number of sectors to read
285mov ax, [WORD nsec]
286 pop bx ; get buffer\r
287 mov ah, 2 ; bios read function\r
288 \r
289 int 13h\r
290\r
291 jb read_error\r
292mov cx, [WORD nsec] ; return number of sectors read
293 ret\r
294\r
295\r
296getinfo: ; get some drive parameters\r
297 mov dl, BOOTDEV ; boot drive is drive C\r
298 mov ah, 8h\r
299 push es
300 int 13h\r
301 pop es
302\r
303 mov al, dh ; max head #\r
304 inc al ; al -> tracks/cyl\r
305 and cx, 3fh ; cl -> secs/track\r
306 mul cl ; ax -> secs/cyl\r
307 mov [WORD spc], ax\r
308 mov [WORD spt], cx\r
309\r
310 ret\r
311\r
312\r
313message: ; write the error message in ds:esi
314 ; to console\r
315 push es\r
316 mov ax,ds\r
317 mov es,ax\r
318\r
319 mov bx, 1 ; bh=0, bl=1 (blue)\r
320 cld\r
321\r
322nextb:\r
323 lodsb ; load a byte into al\r
324 cmp al, 0\r
325 je done\r
326 mov ah, 0eh ; bios int 10, function 0xe\r
327 int 10h ; bios display a byte in tty mode\r
328 jmp nextb\r
329done: pop es\r
330 ret\r
331\r
332putchr:\r
333 push bx\r
334 mov bx, 1 ; bh=0, bl=1 (blue)\r
335 mov ah, 0eh ; bios int 10, function 0xe\r
336 int 10h ; bios display a byte in tty mode\r
337 pop bx\r
338 ret\r
339
340IF SDEBUG\r
341hexout:\r ; print ebx as hex number
342 push cx\r
343 push ax\r
344 mov cx,8 ;output 8 nibbles\r
345\r
346htop:\r
347 rol ebx,4\r
348 mov al,bl\r
349 and al,0fh\r
350 cmp al,0ah\r
351 jb o_digit\r
352 add al,'A'-10\r
353 jmp o_print\r
354o_digit: add al,'0'\r
355o_print: call putchr\r
356 dec cx\r
357 jne htop\r
358; mov al,10\r
359; call putchr\r
360; mov al,13\r
361; call putchr\r
362 mov al,' '
363 call putchr
364 pop ax\r
365 pop cx\r
366 ret\r
367ENDIF\r
368\r
369\r
370read_error:\r
371 mov si, OFFSET eread\r
372boot_exit: ; boot_exit: write error message and halt\r
373 call message ; display error message\r
374halt: jmp halt\r
375\r
376\r
377intro: db 10,'NEXTSTEP boot1 vXX.XX.XX.XX.XX',10,13,0\r
378eread: db 'Read error',10,13,0\r
379
380; the last 2 bytes in the sector contain the signature\r
381d1:\r
382 a2 = 510 - (d1 - start)\r
383 DB a2 dup (0)\r
384 DW 0AA55h\r
385 ENDS\r
386 END\r