VirtualBox

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

最後變更 在這個檔案從83018是 83018,由 vboxsync 提交於 5 年 前

bs3kit: Tried to improove the load time in the boot sector.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.0 KB
 
1; $Id: bs3-bootsector.asm 83018 2020-02-07 13:13:23Z 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-2020 Oracle Corporation
11;
12; This file is part of VirtualBox Open Source Edition (OSE), as
13; available from http://www.alldomusa.eu.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;*********************************************************************************************************************************
41;* Defined Constants And Macros *
42;*********************************************************************************************************************************
43;; Enabled faster loading.
44%define BS3KIT_BOOTSECTOR_FASTER_LOAD
45;; Enabled load progress dots.
46%define BS3KIT_BOOTSECTOR_LOAD_DOTS
47
48
49%ifdef __YASM__
50[map all]
51%endif
52
53;
54; Start with a jump just to follow the convention.
55; Also declare all segments/sections to establish them and their order.
56;
57 ORG 07c00h
58
59BITS 16
60CPU 8086
61start:
62 jmp short bs3InitCode
63 db 0ah ; Should be nop, but this looks better.
64g_OemId: ; 003h
65 db 'BS3Kit', 0ah, 0ah
66
67;
68; DOS 4.0 Extended Bios Parameter Block:
69;
70g_cBytesPerSector: ; 00bh
71 dw 512
72g_cSectorsPerCluster: ; 00dh
73 db 1
74g_cReservedSectors: ; 00eh
75 dw 1
76g_cFATs: ; 010h
77 db 0
78g_cRootDirEntries: ; 011h
79 dw 0
80g_cTotalSectors: ; 013h
81 dw 0
82g_bMediaDescriptor: ; 015h
83 db 0
84g_cSectorsPerFAT: ; 016h
85 dw 0
86g_cPhysSectorsPerTrack: ; 018h
87 dw 18
88g_cHeads: ; 01ah
89 dw 2
90g_cHiddentSectors: ; 01ch
91 dd 1
92g_cLargeTotalSectors: ; 020h - We (ab)use this to indicate the number of sectors to load.
93 dd 0
94g_bBootDrv: ; 024h
95 db 80h
96g_bFlagsEtc: ; 025h
97 db 0
98g_bExtendedSignature: ; 026h
99 db 0x29
100g_dwSerialNumber: ; 027h
101 dd 0x0a458634
102g_abLabel: ; 02bh
103 db 'VirtualBox', 0ah
104g_abFSType: ; 036h
105 db 'RawCode', 0ah
106g_BpbEnd: ; 03ch
107
108
109;
110; Where to real init code starts.
111;
112bs3InitCode:
113 cli
114
115 ; save the registers.
116 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.rax], ax
117 mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.ds], ds
118
119 ; set up the DS segment reister so we can skip the CS prefix when saving more prefixes..
120 mov ax, 0
121 mov ds, ax
122
123 mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rdi], di
124 mov di, BS3_ADDR_REG_SAVE
125 mov [di + BS3REGCTX.rsp], sp
126 mov [di + BS3REGCTX.ss], ss
127 mov [di + BS3REGCTX.rcx], cx
128 mov [di + BS3REGCTX.es], es
129 mov [di + BS3REGCTX.rbp], bp
130
131 ; set up the stack.
132 mov ss, ax
133 mov sp, BS3_ADDR_STACK
134
135 ; Load es and setup bp frame.
136 mov es, ax
137 mov bp, sp
138%if 0
139 mov [bp], ax ; clear the first 8 bytes (terminates the ebp chain)
140 mov [bp + 02h], ax
141 mov [bp + 04h], ax
142 mov [bp + 06h], ax
143%else
144 mov di, sp ; Combine clearing the rbp chain and register save area.
145%endif
146
147 ; Save flags now that we know that there's a valid stack.
148 pushf
149
150 ;
151 ; Clear the register area.
152 ;
153%if 0
154 mov di, BS3_ADDR_REG_SAVE
155 mov cx, BS3REGCTX_size/2
156%else
157 mov cx, (BS3_ADDR_LOAD - BS3_ADDR_STACK) / 2
158%endif
159 cld
160 rep stosw
161
162 ;
163 ; Do basic CPU detection.
164 ;
165
166 ; 0. Load the register save area address into DI to avoid absolute addressing
167 ; when saving additional state. To avoid disp16, offset the address.
168 mov di, BS3_ADDR_REG_SAVE + 0x70
169
170 ; 1. bit 15-bit was fixed to 1 in pre-286 CPUs, and fixed to 0 in 286+.
171 mov ax, [bp - 2]
172 test ah, 080h ; always set on pre 286, clear on 286 and later
173 jnz .pre_80286
174
175 ; 2. On a 286 you cannot popf IOPL and NT from real mode.
176.detect_286_or_386plus:
177CPU 286
178 mov ah, (X86_EFL_IOPL | X86_EFL_NT) >> 8
179 push ax
180 popf
181 pushf
182 cmp ah, [bp - 3]
183 pop ax
184 je .is_386plus
185.is_80286:
186CPU 286
187 smsw [di + BS3REGCTX.cr0 - 0x70]
188.pre_80286:
189CPU 8086
190 mov [di - 0x70 + BS3REGCTX.rbx], bx
191 mov [di - 0x70 + BS3REGCTX.rdx], dx
192 mov [di - 0x70 + BS3REGCTX.rsi], si
193 jmp .do_load
194
195 ; Save 386 registers. We can now skip the CS prefix as DS is flat.
196CPU 386
197.is_386plus:
198 shr eax, 16
199 mov [di - 0x70 + BS3REGCTX.rax+2], ax
200 mov eax, esp
201 shr eax, 16
202 mov [di - 0x70 + BS3REGCTX.rsp+2], ax
203 mov eax, ebp
204 shr eax, 16
205 mov [di - 0x70 + BS3REGCTX.rbp+2], ax
206 mov eax, edi
207 shr eax, 16
208 mov [di - 0x70 + BS3REGCTX.rdi+2], ax
209 shr ecx, 16
210 mov [di - 0x70 + BS3REGCTX.rcx+2], cx
211 mov [di - 0x70 + BS3REGCTX.fs], fs
212 mov [di - 0x70 + BS3REGCTX.gs], gs
213 mov [di - 0x70 + BS3REGCTX.rbx], ebx
214 mov [di - 0x70 + BS3REGCTX.rdx], edx
215 mov [di - 0x70 + BS3REGCTX.rsi], esi
216 mov eax, cr2
217 mov [di - 0x70 + BS3REGCTX.cr2], eax
218 mov eax, cr3
219 mov [di - 0x70 + BS3REGCTX.cr3], eax
220 mov byte [di - 0x70 + BS3REGCTX.bMode], BS3_MODE_RM
221 mov [di - 0x70 + BS3REGCTX.cs], cs
222 xor eax, eax
223 mov ax, start
224 mov [di - 0x70 + BS3REGCTX.rip], eax
225
226 ; Pentium/486+: CR4 requires VME/CPUID, so we need to detect that before accessing it.
227 mov [di - 0x70 + BS3REGCTX.cr4], eax
228 popf ; (restores IOPL+NT)
229 pushfd
230 pop eax
231 mov [di - 0x70 + BS3REGCTX.rflags], eax
232 xor eax, X86_EFL_ID
233 push eax
234 popfd
235 pushfd
236 pop ebx
237 cmp ebx, eax
238 jne .no_cr4
239 mov eax, cr4
240 mov [di - 0x70 + BS3REGCTX.cr4], eax
241.no_cr4:
242 ; Make sure caching is enabled and alignment is off.
243 mov eax, cr0
244 mov [di - 0x70 + BS3REGCTX.cr0], eax
245 and eax, ~(X86_CR0_NW | X86_CR0_CD | X86_CR0_AM)
246 mov cr0, eax
247
248 ; Load all the code.
249.do_load
250 mov [g_bBootDrv], dl
251 call NAME(bs3InitLoadImage)
252%if 0
253 mov al, '='
254 call NAME(bs3PrintChrInAl)
255%endif
256
257 ;
258 ; Call the user 'main' procedure (shouldn't return).
259 ;
260 cld
261 call BS3_SEL_TEXT16:0000h
262
263 ; Panic/hang.
264Bs3Panic:
265 cli
266 jmp Bs3Panic
267
268
269;; For debug and error handling.
270; @uses ax
271bs3PrintHexInAl:
272CPU 286
273 push ax
274 shr al, 4
275 call bs3PrintHexDigitInAl
276 pop ax
277bs3PrintHexDigitInAl:
278 and al, 0fh
279 cmp al, 10
280 jb .decimal
281 add al, 'a' - '0' - 10
282.decimal:
283 add al, '0'
284bs3PrintChrInAl:
285 push bx
286 mov ah, 0eh
287 mov bx, 0ff00h
288 int 10h
289 pop bx
290 ret
291
292
293;;
294; Loads the image off the floppy.
295;
296; This uses g_cLargeTotalSectors to figure out how much to load.
297;
298; Clobbers everything except ebp and esp. Panics on failure.
299;
300; @param dl The boot drive number (from BIOS).
301; @uses ax, cx, bx, esi, di
302;
303BEGINPROC bs3InitLoadImage
304 push bp
305 mov bp, sp
306 push es
307%define bSavedDiskNo byte [bp - 04h]
308 push dx
309%define bMaxSector byte [bp - 06h]
310%define wMaxSector word [bp - 06h]
311 xor ax, ax
312 push ax
313%define bMaxHead byte [bp - 08h]
314 push ax
315%define bMaxCylinder byte [bp - 0ah]
316 push ax
317
318 ;
319 ; Try figure the geometry.
320 ;
321 mov ah, 08h
322 int 13h
323 jc .failure
324 mov bMaxSector, cl
325 mov bMaxHead, dh
326 mov bMaxCylinder, ch
327 mov dl, bSavedDiskNo
328
329%if 0 ; bMaxSector=0x12 (18); bMaxHead=0x01; bMaxCylinder=0x4f (79)
330 mov al, 'S'
331 call bs3PrintChrInAl
332 mov al, bMaxSector
333 call bs3PrintHexInAl
334 mov al, 'H'
335 call bs3PrintChrInAl
336 mov al, bMaxHead
337 call bs3PrintHexInAl
338 mov al, 'C'
339 call bs3PrintChrInAl
340 mov al, bMaxCylinder
341 call bs3PrintHexInAl
342 mov al, ';'
343 call bs3PrintChrInAl
344%endif
345
346%ifndef BS3KIT_BOOTSECTOR_FASTER_LOAD
347 ;
348 ; Load the sectors following the boot sector one at a time (avoids problems).
349 ;
350 mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes.
351 dec si ; Practically max: ca 575 KB, or 1150 sectors. Linker set BS3_MAX_SIZE to 480KB.
352
353 mov di, BS3_ADDR_LOAD / 16 ; The current load segment.
354 mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=2 (1-based)
355 xor dh, dh ; dh/head=0
356.the_load_loop:
357 %if 0
358 mov al, 'c'
359 call bs3PrintChrInAl
360 mov al, ch
361 call bs3PrintHexInAl
362 mov al, 's'
363 call bs3PrintChrInAl
364 mov al, cl
365 call bs3PrintHexInAl
366 mov al, 'h'
367 call bs3PrintChrInAl
368 mov al, dh
369 call bs3PrintHexInAl
370 mov al, ';'
371 call bs3PrintChrInAl
372 %elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS
373 mov al, '.'
374 call bs3PrintChrInAl
375 %endif
376 xor bx, bx
377 mov es, di ; es:bx -> buffer
378 mov ax, 0201h ; al=1 sector; ah=read function
379 int 13h
380 jc .failure
381
382 ; advance to the next sector/head/cylinder.
383 inc cl
384 cmp cl, bMaxSector
385 jbe .adv_addr
386
387 mov cl, 1
388 inc dh
389 cmp dh, bMaxHead
390 jbe .adv_addr
391
392 mov dh, 0
393 inc ch
394
395.adv_addr:
396 add di, 512 / 16
397 dec si
398 jnz .the_load_loop
399
400%else ; BS3KIT_BOOTSECTOR_FASTER_LOAD
401 ;
402 ; Load the sectors following the boot sector, trying to load a whole
403 ; side in each bios call, falling back on single sector reads if we
404 ; run into DMA 64KB boundrary issues (BIOS must tell us).
405 ;
406 mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes.
407 dec si ; Skip the boot sector, it's not part of the test image we execute.
408 mov di, BS3_ADDR_LOAD / 16 ; The current load segment.
409 mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=0 (1-based)
410 xor dh, dh ; dh/head=0
411.the_load_loop:
412 %if 0
413 mov al, 'c'
414 call bs3PrintChrInAl
415 mov al, ch
416 call bs3PrintHexInAl
417 mov al, 's'
418 call bs3PrintChrInAl
419 mov al, cl
420 call bs3PrintHexInAl
421 mov al, 'h'
422 call bs3PrintChrInAl
423 mov al, dh
424 call bs3PrintHexInAl
425 mov al, ';'
426 call bs3PrintChrInAl
427 %elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS
428 mov al, '.'
429 call bs3PrintChrInAl
430 %endif
431 mov ax, wMaxSector ; read to the end of the side by default.
432 sub al, cl
433 inc al
434.read_again:
435 cmp si, ax
436 jae .do_read
437 mov ax, si
438.do_read:
439 mov ah, 02h ; ah=read function
440 xor bx, bx
441 mov es, di ; es:bx -> buffer
442 int 13h
443 jnc .advance_sector
444
445 cmp ah, 9 ; DMA 64KB crossing error
446 jne .failure
447 mov ax, 1 ; Retry reading a single sector.
448 jmp .read_again
449
450 ; advance to the next sector/head/cylinder and address.
451.advance_sector:
452 inc cl
453 cmp cl, bMaxSector
454 jbe .adv_addr
455
456 mov cl, 1
457 inc dh
458 cmp dh, bMaxHead
459 jbe .adv_addr
460
461 mov dh, 0
462 inc ch
463
464.adv_addr:
465 dec si
466 jz .done_reading
467 add di, 512 / 16
468 dec al
469 jnz .advance_sector
470 jmp .the_load_loop
471
472.done_reading:
473%endif ; BS3KIT_BOOTSECTOR_FASTER_LOAD
474%if 0
475 mov al, 'D'
476 call bs3PrintChrInAl
477%elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS
478 mov al, 13
479 call bs3PrintChrInAl
480 mov al, 10
481 call bs3PrintChrInAl
482%endif
483
484 add sp, 3*2
485 pop dx
486 pop es
487 pop bp
488 ret
489
490 ;
491 ; Something went wrong, display a message.
492 ;
493.failure:
494%if 1
495 hlt
496 jmp .failure
497%else
498 push ax
499
500 ; print message
501 mov si, .s_szErrMsg
502.failure_next_char:
503 lodsb
504 call bs3PrintChrInAl
505 cmp si, .s_szErrMsgEnd
506 jb .failure_next_char
507
508 ; panic
509 pop ax
510%if 1
511 mov al, ah
512 push bs3PrintHexInAl
513%endif
514 call Bs3Panic
515.s_szErrMsg:
516 db 13, 10, 'rd err! '
517%endif
518.s_szErrMsgEnd:
519;ENDPROC bs3InitLoadImage - don't want the padding.
520
521
522;
523; Pad the remainder of the sector with int3's and end it with the DOS signature.
524;
525bs3Padding:
526 times ( 510 - ( (bs3Padding - start) % 512 ) ) db 0cch
527 db 055h, 0aah
528
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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