]>
Commit | Line | Data |
---|---|---|
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 | |
27 | BOOTSEG = 00h | |
28 | BOOTOFF = 1000h | |
29 | BUFSZ = 2000h ; 8K disk transfer buffer\r | |
30 | \r | |
31 | ; FDISK partition table in sector 0\r | |
32 | PARTSTART = 1beh ; starting address of partition table\r | |
33 | NUMPART = 4 ; number of partitions in partition table\r | |
34 | PARTSZ = 16 ; each partition table entry is 16 bytes\r | |
35 | BOOT_IND = 0 ; offset of boot indicator in partition table\r | |
36 | BEG_HEAD = 1 ; offset of beginning head\r | |
37 | BEG_SEC = 2 ; offset of beginning sector\r | |
38 | BEG_CYL = 3 ; offset of beginning cylinder\r | |
39 | NAME_OFFSET = 4 ; offset of partition name\r | |
40 | PARTSEC = 8 ; offset of partition sector specifier\r | |
41 | NEXTNAME = 0A7h ; value of boot_ind, means bootable partition\r | |
42 | \r | |
43 | LOADSZ = 88 ; maxiumum possible size of unix boot\r- 44k | |
44 | \r | |
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\r | |
52 | DISKLABEL = 15 ; sector num of 2nd disk label, 1st is trashed by bootsec\r | |
53 | DL_DISKTAB = 44\r | |
54 | \r | |
55 | ; We support disk label version 3 "3Vld" in our little endian world\r | |
56 | DL_V3 = 33566c64h\r | |
57 | \r | |
58 | ; NeXT disktab\r | |
59 | DT_SECSIZE = 48\r | |
60 | DT_BOOT0_BLKNO = 80\r | |
61 | \r\r | |
62 | ; This code is a replacement for boot1. It is loaded at 0x0:0x7c00\r | |
63 | \r | |
64 | start:\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 | ||
82 | a1:\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 | |
96 | IF ( BOOTDEV EQ FLOPPY ) | |
97 | inc edx ; bootdev = 1 for floppy disk | |
98 | ENDIF | |
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 | |
106 | loadboot:\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 | |
118 | IF ( 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 | |
127 | retry_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 | |
151 | read_success1: ; find the NeXT partition\r | |
152 | mov bx,PARTSTART\r | |
153 | mov cx,NUMPART\r | |
154 | \r | |
155 | again:\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 | |
161 | foundNextPart: ; 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 | |
168 | cont:\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 | |
175 | no_fdisk:\r | |
176 | ENDIF | |
177 | ; Read NeXT disk label\r | |
178 | mov eax, DISKLABEL ; Get block number of label\r | |
179 | getLabl:\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 | |
204 | nexsec:\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 | |
222 | spt: DW 0 ; sectors;track (one-based)\r | |
223 | spc: DW 0 ; tracks;cylinder (zero-based)\r | |
224 | nsec: DW 0 ; number of sectors to read | |
225 | \r | |
226 | readSectors: ; 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 | ||
236 | IF ( BOOTDEV EQ FLOPPY ) | |
237 | push eax\r | |
238 | mov al,'.'\r | |
239 | call putchr\r | |
240 | pop eax\r | |
241 | ENDIF\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 | |
268 | last: | |
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 | |
285 | mov 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 | |
292 | mov cx, [WORD nsec] ; return number of sectors read | |
293 | ret\r | |
294 | \r | |
295 | \r | |
296 | getinfo: ; 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 | |
313 | message: ; 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 | |
322 | nextb:\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 | |
329 | done: pop es\r | |
330 | ret\r | |
331 | \r | |
332 | putchr:\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 | ||
340 | IF SDEBUG\r | |
341 | hexout:\r ; print ebx as hex number | |
342 | push cx\r | |
343 | push ax\r | |
344 | mov cx,8 ;output 8 nibbles\r | |
345 | \r | |
346 | htop:\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 | |
354 | o_digit: add al,'0'\r | |
355 | o_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 | |
367 | ENDIF\r | |
368 | \r | |
369 | \r | |
370 | read_error:\r | |
371 | mov si, OFFSET eread\r | |
372 | boot_exit: ; boot_exit: write error message and halt\r | |
373 | call message ; display error message\r | |
374 | halt: jmp halt\r | |
375 | \r | |
376 | \r | |
377 | intro: db 10,'NEXTSTEP boot1 vXX.XX.XX.XX.XX',10,13,0\r | |
378 | eread: db 'Read error',10,13,0\r | |
379 | ||
380 | ; the last 2 bytes in the sector contain the signature\r | |
381 | d1:\r | |
382 | a2 = 510 - (d1 - start)\r | |
383 | DB a2 dup (0)\r | |
384 | DW 0AA55h\r | |
385 | ENDS\r | |
386 | END\r |