]>
Commit | Line | Data |
---|---|---|
819958c6 | 1 | #------------------------------------------------------------------------------\r |
2 | #*\r | |
3 | #* Copyright 2006 - 2007, Intel Corporation \r | |
4 | #* All rights reserved. This program and the accompanying materials \r | |
5 | #* are licensed and made available under the terms and conditions of the BSD License \r | |
6 | #* which accompanies this distribution. The full text of the license may be found at \r | |
7 | #* http://opensource.org/licenses/bsd-license.php \r | |
8 | #* \r | |
9 | #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r | |
10 | #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r | |
11 | #* \r | |
12 | #* bs16.asm\r | |
13 | #* \r | |
14 | #* Abstract:\r | |
15 | #*\r | |
16 | #------------------------------------------------------------------------------\r | |
17 | \r | |
18 | #.MODEL small\r | |
19 | .stack: \r | |
20 | .486p: \r | |
20193e01 | 21 | .code16\r |
819958c6 | 22 | \r |
23 | .equ FAT_DIRECTORY_ENTRY_SIZE, 0x020\r | |
24 | .equ FAT_DIRECTORY_ENTRY_SHIFT, 5\r | |
25 | .equ BLOCK_SIZE, 0x0200\r | |
26 | .equ BLOCK_MASK, 0x01ff\r | |
27 | .equ BLOCK_SHIFT, 9\r | |
28 | # "EFILDR_____"\r | |
29 | .equ LOADER_FILENAME_PART1, 0x04c494645 # "EFIL"\r | |
30 | .equ LOADER_FILENAME_PART2, 0x036315244 # "DR16"\r | |
31 | .equ LOADER_FILENAME_PART3, 0x020202036 # "6___"\r | |
32 | \r | |
d5172f91 | 33 | .org 0x0\r |
ae3d1e91 | 34 | .global _start\r\r |
fd549a4d | 35 | _start:\r |
819958c6 | 36 | Ia32Jump: \r |
37 | jmp BootSectorEntryPoint # JMP inst - 3 bytes\r | |
38 | nop\r | |
39 | \r | |
40 | OemId: .ascii "INTEL " # OemId - 8 bytes\r | |
41 | # BPB data below will be fixed by tool\r | |
42 | SectorSize: .word 0 # Sector Size - 16 bits\r | |
43 | SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits\r | |
44 | ReservedSectors: .word 0 # Reserved Sectors - 16 bits\r | |
45 | NoFats: .byte 0 # Number of FATs - 8 bits\r | |
46 | RootEntries: .word 0 # Root Entries - 16 bits\r | |
47 | Sectors: .word 0 # Number of Sectors - 16 bits\r | |
48 | Media: .byte 0 # Media - 8 bits - ignored\r | |
49 | SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits\r | |
50 | SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored\r | |
51 | Heads: .word 0 # Heads - 16 bits - ignored\r | |
52 | HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored\r | |
53 | LargeSectors: .long 0 # Large Sectors - 32 bits \r | |
54 | PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored\r | |
55 | CurrentHead: .byte 0 # Current Head - 8 bits\r | |
56 | Signature: .byte 0 # Signature - 8 bits - ignored\r | |
57 | VolId: .ascii " " # Volume Serial Number- 4 bytes\r | |
58 | FatLabel: .ascii " " # Label - 11 bytes\r | |
59 | SystemId: .ascii "FAT12 " # SystemId - 8 bytes\r | |
60 | \r | |
61 | BootSectorEntryPoint: \r | |
62 | #ASSUME ds:@code\r | |
63 | #ASSUME ss:@code\r | |
64 | \r | |
65 | # ****************************************************************************\r | |
66 | # Start Print\r | |
67 | # ****************************************************************************\r | |
57b6de77 | 68 | movw $StartString, %si\r |
819958c6 | 69 | call PrintString\r |
70 | \r | |
71 | # ****************************************************************************\r | |
72 | # Print over\r | |
73 | # ****************************************************************************\r | |
74 | \r | |
75 | movw %cs, %ax # ax = 0\r | |
76 | movw %ax, %ss # ss = 0\r | |
77 | addw $0x1000, %ax\r | |
78 | movw %ax, %ds\r | |
79 | \r | |
80 | movw $0x7c00, %sp # sp = 0x7c00\r | |
81 | movw %sp, %bp # bp = 0x7c00\r | |
82 | \r | |
83 | movb $8, %ah # ah = 8 - Get Drive Parameters Function\r | |
84 | movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL\r | |
85 | int $0x13 # Get Drive Parameters\r | |
86 | xorw %ax, %ax # ax = 0\r | |
87 | movb %dh, %al # al = dh\r | |
88 | incb %al # MaxHead = al + 1\r | |
89 | pushw %ax # 0000:7bfe = MaxHead\r | |
90 | movb %cl, %al # al = cl\r | |
91 | andb $0x3f, %al # MaxSector = al & 0x3f\r | |
92 | pushw %ax # 0000:7bfc = MaxSector\r | |
93 | \r | |
94 | cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature\r | |
95 | jne BadBootSector\r | |
96 | movw RootEntries(%bp), %cx # cx = RootEntries\r | |
97 | shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes\r | |
98 | movw %cx, %bx # bx = size of the Root Directory in bytes\r | |
99 | andw $BLOCK_MASK, %bx # See if it is an even number of sectors long\r | |
100 | jne BadBootSector # If is isn't, then the boot sector is bad.\r | |
101 | movw %cx, %bx # bx = size of the Root Directory in bytes\r | |
102 | shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors\r | |
103 | movb NoFats(%bp), %al # al = NoFats\r | |
104 | xorb %ah, %ah # ah = 0 ==> ax = NoFats\r | |
105 | mulw SectorsPerFat(%bp) # ax = NoFats * SectorsPerFat\r | |
106 | addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA\r | |
107 | pushw %ds\r | |
108 | popw %es\r | |
109 | xorw %di, %di # Store directory in es:di = 1000:0000\r | |
110 | call ReadBlocks # Read entire Root Directory\r | |
111 | addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)\r | |
112 | movw %ax, (%bp) # Save FirstClusterLBA (FirstDataSector) for later use\r | |
113 | \r | |
114 | # dx - variable storage (initial value is 0)\r | |
115 | # bx - loader (initial value is 0)\r | |
116 | xorw %dx, %dx\r | |
117 | xorw %bx, %bx\r | |
118 | \r | |
119 | FindEFILDR: \r | |
120 | cmpl $LOADER_FILENAME_PART1, (%di) # Compare to "EFIL"\r | |
121 | jne FindVARSTORE\r | |
122 | cmpl $LOADER_FILENAME_PART2, 4(%di) \r | |
123 | jne FindVARSTORE\r | |
124 | cmpl $LOADER_FILENAME_PART3, 7(%di) \r | |
125 | jne FindVARSTORE\r | |
126 | movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------\r | |
127 | testw %dx, %dx\r | |
128 | je FindNext # Efivar.bin is not loaded\r | |
129 | jmp FoundAll\r | |
130 | \r | |
131 | FindVARSTORE: \r | |
132 | ##if the file is not loader file, see if it's "EFIVAR BIN"\r | |
133 | cmpl $0x56494645, (%di) # Compare to "EFIV"\r | |
134 | jne FindNext\r | |
135 | cmpl $0x20205241, 4(%di) # Compare to "AR "\r | |
136 | jne FindNext\r | |
137 | cmpl $0x4e494220, 7(%di) # Compare to " BIN"\r | |
138 | jne FindNext\r | |
139 | movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------\r | |
140 | addw $26, %dx\r | |
141 | testw %bx, %bx\r | |
142 | je FindNext # Efildr is not loaded\r | |
143 | jmp FoundAll\r | |
144 | \r | |
145 | FindNext: \r | |
146 | # go to next find\r | |
147 | addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di\r | |
148 | subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx\r | |
149 | # TODO: jump to FindVarStore if ...\r | |
150 | jne FindEFILDR\r | |
151 | jmp NotFoundAll\r | |
152 | \r | |
153 | FoundAll: \r | |
154 | FoundEFILDR: \r | |
155 | movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------\r | |
156 | movw %cs, %ax # Destination = 2000:0000\r | |
157 | addw $0x2000, %ax\r | |
158 | movw %ax, %es\r | |
159 | xorw %di, %di\r | |
160 | ReadFirstClusterOfEFILDR: \r | |
161 | movw %cx, %ax # ax = StartCluster\r | |
162 | subw $2, %ax # ax = StartCluster - 2\r | |
163 | xorb %bh, %bh\r | |
164 | movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster\r | |
165 | pushw %dx\r | |
166 | mulw %bx\r | |
167 | popw %dx # ax = (StartCluster - 2) * SectorsPerCluster\r | |
168 | addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r | |
169 | xorb %bh, %bh\r | |
170 | movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster\r | |
171 | pushw %es\r | |
172 | call ReadBlocks\r | |
173 | popw %ax\r | |
174 | JumpIntoFirstSectorOfEFILDR: \r | |
175 | movw %ax, JumpSegment(%bp)\r | |
176 | JumpFarInstruction: \r | |
177 | .byte 0xea\r | |
178 | JumpOffset: \r | |
179 | .word 0x000\r | |
180 | JumpSegment: \r | |
181 | .word 0x2000\r | |
182 | \r | |
183 | \r | |
184 | PrintString: \r | |
185 | movw $0xb800, %ax\r | |
186 | movw %ax, %es\r | |
187 | movw $0x7c0, %ax\r | |
188 | movw %ax, %ds\r | |
189 | movw $7, %cx\r | |
190 | movw $160, %di\r | |
191 | rep\r | |
192 | movsw\r | |
193 | ret\r | |
194 | # ****************************************************************************\r | |
195 | # ReadBlocks - Reads a set of blocks from a block device\r | |
196 | #\r | |
197 | # AX = Start LBA\r | |
198 | # BX = Number of Blocks to Read\r | |
199 | # ES:DI = Buffer to store sectors read from disk\r | |
200 | # ****************************************************************************\r | |
201 | \r | |
202 | # cx = Blocks\r | |
203 | # bx = NumberOfBlocks\r | |
204 | # si = StartLBA\r | |
205 | \r | |
206 | ReadBlocks: \r | |
207 | pusha\r | |
208 | addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA\r | |
209 | addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA\r | |
210 | movl %eax, %esi # esi = Start LBA\r | |
211 | movw %bx, %cx # cx = Number of blocks to read\r | |
212 | ReadCylinderLoop: \r | |
213 | movw $0x7bfc, %bp # bp = 0x7bfc\r | |
214 | movl %esi, %eax # eax = Start LBA\r | |
215 | xorl %edx, %edx # edx = 0\r | |
216 | movzwl (%bp), %ebx # bx = MaxSector\r | |
217 | divl %ebx # ax = StartLBA / MaxSector\r | |
218 | incw %dx # dx = (StartLBA % MaxSector) + 1\r | |
219 | subw %dx, %bx # bx = MaxSector - Sector\r | |
220 | incw %bx # bx = MaxSector - Sector + 1\r | |
221 | cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)\r | |
222 | jg LimitTransfer\r | |
223 | movw %cx, %bx # bx = Blocks\r | |
224 | LimitTransfer: \r | |
225 | pushw %cx\r | |
226 | movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector\r | |
227 | xorw %dx, %dx # dx = 0\r | |
228 | divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder \r | |
229 | # dx = ax % (MaxHead + 1) = Head\r | |
230 | \r | |
231 | pushw %bx # Save number of blocks to transfer\r | |
232 | movb %dl, %dh # dh = Head\r | |
233 | movw $0x7c00, %bp # bp = 0x7c00\r | |
234 | movb PhysicalDrive(%bp), %dl # dl = Drive Number\r | |
235 | movb %al, %ch # ch = Cylinder\r | |
236 | movb %bl, %al # al = Blocks\r | |
237 | movb $2, %ah # ah = Function 2\r | |
238 | movw %di, %bx # es:bx = Buffer address\r | |
239 | int $0x13\r | |
240 | jc DiskError\r | |
241 | popw %bx\r | |
242 | popw %cx\r | |
243 | movzwl %bx, %ebx\r | |
244 | addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks\r | |
245 | subw %bx, %cx # Blocks = Blocks - NumberOfBlocks\r | |
246 | movw %es, %ax\r | |
247 | shlw $(BLOCK_SHIFT-4),%bx\r | |
248 | addw %bx, %ax\r | |
249 | movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE\r | |
250 | cmpw $0, %cx\r | |
251 | jne ReadCylinderLoop\r | |
252 | popa\r | |
253 | ret\r | |
254 | \r | |
255 | # ****************************************************************************\r | |
256 | # ERROR Condition:\r | |
257 | # ****************************************************************************\r | |
258 | NotFoundAll: \r | |
259 | ## if we found EFILDR, continue\r | |
260 | testw %bx, %bx\r | |
261 | jne FoundEFILDR\r | |
262 | BadBootSector: \r | |
263 | DiskError: \r | |
57b6de77 | 264 | movw $ErrorString, %si\r |
819958c6 | 265 | call PrintString\r |
266 | Halt: \r | |
267 | jmp Halt\r | |
268 | \r | |
269 | StartString: \r | |
270 | .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c\r | |
271 | ErrorString: \r | |
272 | .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c\r | |
273 | \r | |
274 | # ****************************************************************************\r | |
275 | # LBA Offset for BootSector, need patched by tool for HD boot.\r | |
276 | # ****************************************************************************\r | |
277 | \r | |
20193e01 | 278 | .org 0x01fa\r |
819958c6 | 279 | LBAOffsetForBootSector: \r |
280 | .long 0x0\r | |
281 | \r | |
282 | # ****************************************************************************\r | |
283 | # Sector Signature\r | |
284 | # ****************************************************************************\r | |
285 | \r | |
20193e01 | 286 | .org 0x01fe\r |
819958c6 | 287 | SectorSignature: \r |
288 | .word 0xaa55 # Boot Sector Signature\r | |
289 | \r | |
290 | \r | |
291 | \r |