VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm@ 66182

Last change on this file since 66182 was 60676, checked in by vboxsync, 9 years ago

bs3kit: updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.1 KB
Line 
1; $Id: bs3-bootsector.asm 60676 2016-04-24 11:04:57Z vboxsync $
2;; @file
3; Generic bootsector for BS3.
4;
5; This sets up stack at %fff0 and loads the next sectors from the floppy at
6; %10000 (1000:0000 in real mode), then starts executing at cs:ip=1000:0000.
7;
8
9;
10; Copyright (C) 2007-2016 Oracle Corporation
11;
12; This file is part of VirtualBox Open Source Edition (OSE), as
13; available from http://www.virtualbox.org. This file is free software;
14; you can redistribute it and/or modify it under the terms of the GNU
15; General Public License (GPL) as published by the Free Software
16; Foundation, in version 2 as it comes in the "COPYING" file of the
17; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19;
20; The contents of this file may alternatively be used under the terms
21; of the Common Development and Distribution License Version 1.0
22; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
23; VirtualBox OSE distribution, in which case the provisions of the
24; CDDL are applicable instead of those of the GPL.
25;
26; You may elect to license modified versions of this file under the
27; terms and conditions of either the GPL or the CDDL or both.
28;
29
30
31
32;*********************************************************************************************************************************
33;* Header Files *
34;*********************************************************************************************************************************
35%include "bs3kit.mac"
36%include "iprt/asmdefs.mac"
37%include "iprt/x86.mac"
38
39
40%ifdef __YASM__
41[map all]
42%endif
43
44;
45; Start with a jump just to follow the convention.
46; Also declare all segments/sections to establish them and their order.
47;
48 ORG 07c00h
49
50BITS 16
51CPU 8086
52start:
53 jmp short bs3InitCode
54 db 0ah ; Should be nop, but this looks better.
55g_OemId: ; 003h
56 db 'BS3Kit', 0ah, 0ah
57
58;
59; DOS 4.0 Extended Bios Parameter Block:
60;
61g_cBytesPerSector: ; 00bh
62 dw 512
63g_cSectorsPerCluster: ; 00dh
64 db 1
65g_cReservedSectors: ; 00eh
66 dw 1
67g_cFATs: ; 010h
68 db 0
69g_cRootDirEntries: ; 011h
70 dw 0
71g_cTotalSectors: ; 013h
72 dw 0
73g_bMediaDescriptor: ; 015h
74 db 0
75g_cSectorsPerFAT: ; 016h
76 dw 0
77g_cPhysSectorsPerTrack: ; 018h
78 dw 18
79g_cHeads: ; 01ah
80 dw 2
81g_cHiddentSectors: ; 01ch
82 dd 1
83g_cLargeTotalSectors: ; 020h - We (ab)use this to indicate the number of sectors to load.
84 dd 0
85g_bBootDrv: ; 024h
86 db 80h
87g_bFlagsEtc: ; 025h
88 db 0
89g_bExtendedSignature: ; 026h
90 db 0x29
91g_dwSerialNumber: ; 027h
92 dd 0x0a458634
93g_abLabel: ; 02bh
94 db 'VirtualBox', 0ah
95g_abFSType: ; 036h
96 db 'RawCode', 0ah
97g_BpbEnd: ; 03ch
98
99
100;
101; Where to real init code starts.
102;
103bs3InitCode:
104 cli
105
106 ; save the registers.
107 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.rax], ax
108 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.rsp], sp
109 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.ss], ss
110 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.ds], ds
111
112 ; set up the segment reisters and stack.
113 mov ax, 0
114 mov ds, ax
115 mov ss, ax
116 mov sp, BS3_ADDR_STACK
117
118 ; Save more registers, without needing cs prefix.
119 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rcx], cx
120 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rdi], di
121 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.es], es
122 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rbp], bp
123
124 ; Load es and setup bp frame.
125 mov es, ax
126 mov bp, sp
127 mov [bp], ax ; clear the first 8 bytes (terminates the ebp chain)
128 mov [bp + 02h], ax
129 mov [bp + 04h], ax
130 mov [bp + 06h], ax
131
132 ; Save flags now that we know that there's a valid stack.
133 pushf
134
135 ;
136 ; Clear the register area.
137 ;
138 mov di, BS3_ADDR_REG_SAVE
139 mov cx, BS3REGCTX_size/2
140 cld
141 rep stosw
142
143 ;
144 ; Do basic CPU detection.
145 ;
146
147 ; 1. bit 15-bit was fixed to 1 in pre-286 CPUs, and fixed to 0 in 286+.
148 mov ax, [bp - 2]
149 test ah, 080h ; always set on pre 286, clear on 286 and later
150 jnz .pre_80286
151
152 ; 2. On a 286 you cannot popf IOPL and NT from real mode.
153.detect_286_or_386plus:
154CPU 286
155 mov ah, (X86_EFL_IOPL | X86_EFL_NT) >> 8
156 push ax
157 popf
158 pushf
159 cmp ah, [bp - 3]
160 pop ax
161 je .is_386plus
162.is_80286:
163CPU 286
164 smsw [BS3_ADDR_REG_SAVE + BS3REGCTX.cr0]
165.pre_80286:
166CPU 8086
167 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rbx], bx
168 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rdx], dx
169 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rsi], si
170 jmp .do_load
171
172 ; Save 386 registers. We can now skip the CS prefix as DS is flat.
173CPU 386
174.is_386plus:
175 shr eax, 16
176 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rax+2], ax
177 mov eax, esp
178 shr eax, 16
179 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rsp+2], ax
180 mov eax, ebp
181 shr eax, 16
182 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rbp+2], ax
183 shr edi, 16
184 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rdi+2], di
185 shr ecx, 16
186 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rcx+2], cx
187 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.fs], fs
188 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.gs], gs
189 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rbx], ebx
190 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rdx], edx
191 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rsi], esi
192 mov eax, cr2
193 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.cr2], eax
194 mov eax, cr3
195 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.cr3], eax
196 mov byte [BS3_ADDR_REG_SAVE + BS3REGCTX.bMode], BS3_MODE_RM
197 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.cs], cs
198 xor eax, eax
199 mov ax, start
200 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.rip], eax
201
202 ; Pentium/486+: CR4 requires VME/CPUID, so we need to detect that before accessing it.
203 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.cr4], eax
204 popf ; (restores IOPL+NT)
205 pushfd
206 pop eax
207 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rflags], eax
208 xor eax, X86_EFL_ID
209 push eax
210 popfd
211 pushfd
212 pop ebx
213 cmp ebx, eax
214 jne .no_cr4
215 mov eax, cr4
216 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.cr4], eax
217.no_cr4:
218 ; Make sure caching is enabled and alignment is off.
219 mov eax, cr0
220 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.cr0], eax
221 and eax, ~(X86_CR0_NW | X86_CR0_CD | X86_CR0_AM)
222 mov cr0, eax
223
224 ; Load all the code.
225.do_load
226 mov [g_bBootDrv], dl
227 call NAME(bs3InitLoadImage)
228%if 0
229 mov al, '='
230 call NAME(bs3PrintChrInAl)
231%endif
232
233 ;
234 ; Call the user 'main' procedure (shouldn't return).
235 ;
236 cld
237 call BS3_SEL_TEXT16:0000h
238
239 ; Panic/hang.
240Bs3Panic:
241 cli
242 jmp Bs3Panic
243
244
245;; For debug and error handling.
246; @uses ax
247bs3PrintHexInAl:
248CPU 286
249 push ax
250 shr al, 4
251 call bs3PrintHexDigitInAl
252 pop ax
253bs3PrintHexDigitInAl:
254 and al, 0fh
255 cmp al, 10
256 jb .decimal
257 add al, 'a' - '0' - 10
258.decimal:
259 add al, '0'
260bs3PrintChrInAl:
261 push bx
262 mov ah, 0eh
263 mov bx, 0ff00h
264 int 10h
265 pop bx
266 ret
267
268
269;;
270; Loads the image off the floppy.
271;
272; This uses g_cLargeTotalSectors to figure out how much to load.
273;
274; Clobbers everything except ebp and esp. Panics on failure.
275;
276; @param dl The boot drive number (from BIOS).
277; @uses ax, cx, bx, esi, di
278;
279BEGINPROC bs3InitLoadImage
280 push bp
281 mov bp, sp
282 push es
283%define bSavedDiskNo byte [bp - 04h]
284 push dx
285%define bMaxSector byte [bp - 06h]
286 xor ax, ax
287 push ax
288%define bMaxHead byte [bp - 08h]
289 push ax
290%define bMaxCylinder byte [bp - 0ah]
291 push ax
292
293 ;
294 ; Try figure the geometry.
295 ;
296 mov ah, 08h
297 int 13h
298 jc .failure
299 mov bMaxSector, cl
300 mov bMaxHead, dh
301 mov bMaxCylinder, ch
302 mov dl, bSavedDiskNo
303
304 ;
305 ; Reload all the sectors one at a time (avoids problems).
306 ;
307 mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes.
308 dec si
309 mov di, BS3_ADDR_LOAD / 16 ; The current load segment.
310 mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=2 (1-based)
311 xor dh, dh ; dh/head=0
312.the_load_loop:
313%if 0
314 mov al, 'c'
315 call bs3PrintChrInAl
316 mov al, ch
317 call bs3PrintHexInAl
318 mov al, 's'
319 call bs3PrintChrInAl
320 mov al, cl
321 call bs3PrintHexInAl
322 mov al, 'h'
323 call bs3PrintChrInAl
324 mov al, dh
325 call bs3PrintHexInAl
326 mov al, ';'
327 call bs3PrintChrInAl
328%endif
329 xor bx, bx
330 mov es, di ; es:bx -> buffer
331 mov ax, 0201h ; al=1 sector; ah=read function
332 int 13h
333 jc .failure
334
335 ; advance to the next sector/head/cylinder.
336 inc cl
337 cmp cl, bMaxSector
338 jbe .adv_addr
339
340 mov cl, 1
341 inc dh
342 cmp dh, bMaxHead
343 jbe .adv_addr
344
345 mov dh, 0
346 inc ch
347
348.adv_addr:
349 add di, 512 / 16
350 dec si
351 jnz .the_load_loop
352%if 0
353 mov al, 'D'
354 call bs3PrintChrInAl
355%endif
356
357 add sp, 3*2
358 pop dx
359 pop es
360 pop bp
361 ret
362
363 ;
364 ; Something went wrong, display a message.
365 ;
366.failure:
367 push ax
368
369 ; print message
370 mov si, .s_szErrMsg
371.failure_next_char:
372 lodsb
373 call bs3PrintChrInAl
374 cmp si, .s_szErrMsgEnd
375 jb .failure_next_char
376
377 ; panic
378 pop ax
379%if 1
380 mov al, ah
381 push bs3PrintHexInAl
382%endif
383 call Bs3Panic
384.s_szErrMsg:
385 db 13, 10, 'rd err! '
386.s_szErrMsgEnd:
387;ENDPROC bs3InitLoadImage - don't want the padding.
388
389
390;
391; Pad the remainder of the sector with int3's and end it with the DOS signature.
392;
393bs3Padding:
394 times ( 510 - ( (bs3Padding - start) % 512 ) ) db 0cch
395 db 055h, 0aah
396
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette