Annotation of prex/boot/i386/utils/bootsect/bootsect.S, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /**
31: * bootsect.s - Boot sector for FAT
32: *
33: * The boot sector is 512 byte code to load the OS image. It is loaded
34: * to address 0:7c00 by POST BIOS.
35: * The boot sector searches the target file within the root directory of
36: * FAT file system, and loads it to predefined memory address. Then, it
37: * jumps to the first byte of the loaded image.
38: *
39: * All disk access are done by using BIOS Int13h interface. The BIOS
40: * parameter block (BPB) has the disk/FAT information, and it exists
41: * in the first portion of the FAT boot sector. It must be filled by the
42: * FAT format utility, or the prex kernel install utility (mkboot.com).
43: * This program assumes that correct BPB is stored in the boot sector.
44: *
45: * Limitation:
46: * - Support only FAT12/16. FAT32 is not supported.
47: *
48: * Memory usage:
49: * > 5000 - 6FFF ... Disk work area
50: * > 7000 - 7BFF ... Stack
51: * > 7C00 - 7DFF ... This boot sector
52: * >10000 - ... FAT cache
53: * >20000 - ... Data cache
54: * >30000 - ... Image load address
55: */
56: .code16
57: .text
58: .align 1
59:
60: # Memory locations
61: #define BOOT_STACK 0x7c00
62:
63: #define LOAD_ADDR 0x30000
64: #define ENTRY_SEG 0x3000
65: #define ENTRY_OFF 0x0000
66:
67: #define WORK_AREA 0x5000
68: #define FAT_SEG 0x1000
69: #define DATA_SEG 0x2000
70:
71: #define LOAD_MAX 0xA0000
72:
73: # FAT Directory entry
74: #define F_NAME 0
75: #define F_ATTR 11
76: #define F_RESERVED 12
77: #define F_TIME 22
78: #define F_DATA 24
79: #define F_CLUSTER 26
80: #define F_SIZE 28
81:
82: #define DIR_SIZE 32
83: #define DIRENT_PER_SECTOR 16
84:
85: # BIOS parameter block (BPB) location (%bp points to 0x7c00)
86: #define OEM_ID 0x03(%bp)
87: #define BYTE_PER_SECTOR 0x0b(%bp)
88: #define SECT_PER_CLUSTER 0x0d(%bp)
89: #define RESERVED_SECTORS 0x0e(%bp)
90: #define NUM_OF_FATS 0x10(%bp)
91: #define ROOT_ENTRIES 0x11(%bp)
92: #define TOTAL_SECTORS 0x13(%bp)
93: #define MEDIA_DESCRIPTOR 0x15(%bp)
94: #define SECTORS_PER_FAT 0x16(%bp)
95: #define SECTORS_PER_TRACK 0x18(%bp)
96: #define HEADS 0x1a(%bp)
97: #define HIDDEN_SECTORS 0x1c(%bp)
98: #define BIG_TOTAL_SECTORS 0x20(%bp)
99: #define PHYSICAL_DRIVE 0x24(%bp)
100: #define EXT_BOOT_SIGNATURE 0x26(%bp)
101: #define SERIAL_NO 0x27(%bp)
102: #define VOLUME_ID 0x2b(%bp)
103: #define FILE_SYS_ID 0x36(%bp)
104:
105: #define FILE_SYS_ID_NUM 0x3a(%bp)
106:
107: # Local data area (Note: These data will overlap the existing code)
108: #define FAT_START 0x40(%bp)
109: #define DATA_START 0x44(%bp)
110:
111: .global _boot
112:
113: #
114: # Boot the system
115: #
116: _boot:
117: jmp start # Skip BPB
118: nop # Nop is for DOS compatibility
119:
120: #
121: # BPB
122: #
123: .ascii "PREX1.00"
124: .fill 0x33, 1, 0 # Drive parameter must be
125: # filled by intaller
126:
127: #
128: # Setup stack and segment registers
129: #
130: start:
131: cli
132: cld # Clear direction flag
133: xorl %eax, %eax # Set EAX to zero
134: movw %ax, %ds
135: movw %ax, %es
136: movw %ax, %ss
137: movw $(BOOT_STACK), %sp
138: movw %sp, %bp # EBP = Bios Parameter Block
139: sti
140:
141: #
142: # Display boot message
143: #
144: movw $load_msg, %si
145: movw $21, %cx
146: call puts
147:
148: #
149: # Store disk information
150: #
151: movl HIDDEN_SECTORS, %ebx # Get hidden sector
152: movw RESERVED_SECTORS, %ax # Add reserved sector
153: addl %eax, %ebx # High 16 bit of EAX is 0
154: movl %ebx, FAT_START # FAT start = hidden + reserved
155:
156: movzbw NUM_OF_FATS, %ax # Normally 2
157: mulw SECTORS_PER_FAT # AX = Num of sector of FATs
158: addl %ebx, %eax # EAX = Start of root directory
159:
160: movw ROOT_ENTRIES, %bx
161: shrw $4, %bx # / 16 = DIRENT_PER_SECTOR
162: movw %bx, %cx # CX = Num of sectors for root directory
163:
164: addl %eax, %ebx # DATA start = FAT start + root
165: movl %ebx, DATA_START # Start sector of data area
166:
167: #
168: # Find the OS image in the root directory
169: #
170: # EAX = Start sector of root
171: next_sector:
172: pushw %cx
173: movl $(WORK_AREA), %ebx
174: pushw %bx
175: call read_sector # Read 1 sector in root
176: popw %di # DI = dir_entry
177: movw $(DIRENT_PER_SECTOR), %cx # CX = directory count
178: next_entry:
179: cmpb $0, (%di) # End of dir entry ?
180: je error # Not found
181: testb $0x18, F_ATTR(%di) # Subdir or Volume ?
182: jnz not_file # Skip it
183: pusha
184: movw $11, %cx # File name + ext = 11 byte
185: movw $image_name, %si
186: repe # Compare file name
187: cmpsb
188: popa
189: je found_file
190: not_file:
191: addw $(DIR_SIZE), %di # Check next directory entry
192: loop next_entry
193: popw %cx
194: loop next_sector
195: # Fall through
196: #
197: # Error case
198: #
199: error:
200: movw $err_msg, %si
201: movw $5, %cx
202: call puts
203: hang:
204: hlt
205: jmp hang # Stop here
206:
207: #
208: # Load image
209: #
210: found_file:
211: movzwl F_CLUSTER(%di), %eax # EAX = 1st cluster of loader
212: movl $(LOAD_ADDR), %ebx # EBX = 32bit load address
213: load_next:
214: call read_cluster # Read cluster of loader
215: call next_cluster # Get next cluster# in EAX
216: jb load_next # EOF ?
217:
218: #
219: # Turn fdd motor off
220: #
221: movw $0x3f2, %dx
222: xorb %al, %al
223: outb %al, %dx
224:
225: #
226: # Jump to loaded image
227: #
228: ljmp $0x3000, $0x0
229:
230: #
231: # Puts - Print string
232: #
233: # Entry:
234: # SI - Pointer to message string
235: # CX - Number of character
236: #
237: puts:
238: lodsb
239: movb $0x0e, %ah
240: movw $0x0007, %bx
241: int $0x10
242: loop puts
243: ret
244:
245: #
246: # next_cluster - Return next cluster
247: #
248: # Entry:
249: # EAX - Current cluter#
250: #
251: # Exit:
252: # AF - End of cluster
253: # EAX - Next cluter#
254: #
255: # Modified:
256: # Flags,CX,EDX,SI,DI
257: #
258: next_cluster:
259: pushl %ebx
260: movw %ax, %di # Save cluster# in DI
261:
262: movw $0xfff8, %si # Set default EOF to FAT16
263:
264: movl %eax, %ecx
265: shll $1, %eax # * 2
266:
267: cmpb $0x36, FILE_SYS_ID_NUM # ID is 'FAT16' ?
268: je fat_16
269: addl %ecx, %eax # * 3
270: shrl $1, %eax # / 2
271: movw $0xff8, %si # EOF for FAT12
272: fat_16:
273: # EAX - Offset of FAT entry
274: xorw %dx, %dx
275: divw BYTE_PER_SECTOR
276: addl FAT_START, %eax # EAX = Sector# for FAT
277: # DX = Offset in sector
278: movl $(WORK_AREA), %ebx
279: pushw %bx
280: call read_sector # Read 2 sector for border
281: call read_sector # data
282: popw %bx
283: addw %dx, %bx
284: movw (%bx), %ax
285: cmpw $0xfff8, %si # FAT16 ?
286: je chk_end
287:
288: shrw $1, %di
289: jc odd_pos
290: andb $0x0f, %ah
291: jmp chk_end
292: odd_pos:
293: shrw $4, %ax
294: chk_end:
295: cmpw %si, %ax
296: popl %ebx
297: ret
298:
299: #
300: # read_cluster - Read one cluster
301: #
302: # Entry:
303: # EBX - 32-bit pointer to buffer
304: # EAX - Cluster number
305: #
306: # Exit:
307: # EBX - Point to next buffer
308: #
309: # Modified:
310: # flags,ECX,ECX,EDX
311: #
312: read_cluster:
313: pushl %eax
314: decw %ax # Translate clust# to sec#
315: decw %ax
316: xorl %ecx, %ecx
317: movb SECT_PER_CLUSTER, %cl
318: mull %ecx
319: addl DATA_START, %eax # EAX = Read sec#
320: # CX = Read sector size
321: read_loop:
322: call read_sector
323: cmpl $(LOAD_MAX), %ebx
324: jae error
325: loop read_loop
326: popl %eax
327: ret
328:
329: #
330: # read_sector - Read one sector
331: #
332: # Entry:
333: # EBX - 32-bit pointer to buffer
334: # EAX - Logical sector# to read
335: #
336: # Exit:
337: # EBX - Pointer to next buffer
338: # EAX - Next sector
339: #
340: # Modified:
341: # Flags
342: #
343: read_sector:
344: pushal
345: pushw %ds
346: pushw %es
347:
348: movl %eax, %esi # ESI = buffer
349:
350: movzwl SECTORS_PER_TRACK, %ecx # Get sec/track
351: xorl %edx, %edx
352: divl %ecx # EAX = track#
353: # DX = sec#
354: movw $(DATA_SEG), %cx # Check in cache
355: leaw last_data, %di
356: cmpl DATA_START, %esi
357: jae data_reqest
358: movw $(FAT_SEG), %cx
359: leaw last_fat, %di
360: data_reqest:
361: # CX = Cached segment
362: pushal # [DI] = Cached track
363: movw %cx, %es
364: xorw %bx, %bx # ES:BX = Cache address
365: cmpl (%di), %eax # Last track ?
366: je hit_cache
367: movl %eax, (%di) # Save current track#
368: call read_track
369: hit_cache:
370: popal
371:
372: pushw %es
373: popw %ds
374:
375: shlw $9, %dx # sec# * 512
376: movw %dx, %si # DS:SI = Offset in cache
377:
378: movw %bx, %di # [EBX] -> ES:[DI]
379: andw $0xf, %di
380: shrl $4, %ebx
381: movw %bx, %es
382:
383: mov $512, %cx # Copy 1 sector
384: rep
385: movsb
386:
387: popw %es
388: popw %ds
389: popal
390:
391: addl $512, %ebx # Next buffer
392: incl %eax # Next sector
393: ret
394:
395: #
396: # read_track - Read one track
397: #
398: # Entry:
399: # ES:[BX] - Pointer to buffer
400: # EAX - Track number to read
401: #
402: # Exit:
403: # None
404: #
405: # Modified:
406: # Flags,EAX,ECX,EDX
407: #
408: read_track:
409: movzwl HEADS, %ecx # Get num of head
410: xorl %edx, %edx
411: divl %ecx # AX = cyl#
412: # DL = head#
413:
414: movb %al, %ch # CH = cyl# (low 8 bits)
415: andb $3, %ah
416: shlb $6, %ah
417: orb $1, %ah
418: movb %ah, %cl # CL[7:6] = cyl# (high 2 bits)
419: # CL[5:0] = sec# = 1
420: movb %dl, %dh # DH = Head#
421: movw SECTORS_PER_TRACK, %ax # AL = Num of sectors to read
422: movb $2, %ah # AH = 02h (Read Disk Sectors)
423: movb PHYSICAL_DRIVE, %dl # DL = Drive#
424: int $0x13 # Invoke Disk BIOS
425: jc error
426: ret
427:
428: #
429: # Local Data
430: #
431: last_fat: .long 0xffffffff
432: last_data: .long 0xffffffff
433:
434: load_msg: .ascii "Loading "
435: image_name: .ascii "PREXOS "
436: crlf: .byte 0x0a, 0x0d
437: err_msg: .ascii "Error"
438:
439: .org 510
440: .word 0xaa55
CVSweb