VirtualBox

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

Last change on this file since 86728 was 83020, checked in by vboxsync, 5 years ago

bs3kit/bootsector: Restore the error mesage that was disabled for space reasons while debugging.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1; $Id: bs3-bootsector.asm 83020 2020-02-07 13:35:07Z 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.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;*********************************************************************************************************************************
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
316 ;
317 ; Try figure the geometry.
318 ;
319 mov ah, 08h
320 int 13h
321 jc .failure
322 and cl, 63 ; only the sector count.
323 mov bMaxSector, cl
324 mov bMaxHead, dh
325 mov dl, bSavedDiskNo
326
327%if 0 ; bMaxSector=0x12 (18); bMaxHead=0x01; bMaxCylinder=0x4f (79)
328 mov al, 'S'
329 call bs3PrintChrInAl
330 mov al, bMaxSector
331 call bs3PrintHexInAl
332 mov al, 'H'
333 call bs3PrintChrInAl
334 mov al, bMaxHead
335 call bs3PrintHexInAl
336 mov al, 'C'
337 call bs3PrintChrInAl
338 mov al, ch ; first 8-bit of cylinder count.
339 call bs3PrintHexInAl
340 mov al, ';'
341 call bs3PrintChrInAl
342%endif
343
344%ifndef BS3KIT_BOOTSECTOR_FASTER_LOAD
345 ;
346 ; Load the sectors following the boot sector one at a time (avoids problems).
347 ;
348 mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes.
349 dec si ; Practically max: ca 575 KB, or 1150 sectors. Linker set BS3_MAX_SIZE to 480KB.
350
351 mov di, BS3_ADDR_LOAD / 16 ; The current load segment.
352 mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=2 (1-based)
353 xor dh, dh ; dh/head=0
354.the_load_loop:
355 %if 0
356 mov al, 'c'
357 call bs3PrintChrInAl
358 mov al, ch
359 call bs3PrintHexInAl
360 mov al, 's'
361 call bs3PrintChrInAl
362 mov al, cl
363 call bs3PrintHexInAl
364 mov al, 'h'
365 call bs3PrintChrInAl
366 mov al, dh
367 call bs3PrintHexInAl
368 mov al, ';'
369 call bs3PrintChrInAl
370 %elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS
371 mov al, '.'
372 call bs3PrintChrInAl
373 %endif
374 xor bx, bx
375 mov es, di ; es:bx -> buffer
376 mov ax, 0201h ; al=1 sector; ah=read function
377 int 13h
378 jc .failure
379
380 ; advance to the next sector/head/cylinder.
381 inc cl
382 cmp cl, bMaxSector
383 jbe .adv_addr
384
385 mov cl, 1
386 inc dh
387 cmp dh, bMaxHead
388 jbe .adv_addr
389
390 mov dh, 0
391 inc ch
392
393.adv_addr:
394 add di, 512 / 16
395 dec si
396 jnz .the_load_loop
397
398%else ; BS3KIT_BOOTSECTOR_FASTER_LOAD
399 ;
400 ; Load the sectors following the boot sector, trying to load a whole
401 ; side in each bios call, falling back on single sector reads if we
402 ; run into DMA 64KB boundrary issues (BIOS must tell us).
403 ;
404 mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes.
405 dec si ; Skip the boot sector, it's not part of the test image we execute.
406 mov di, BS3_ADDR_LOAD / 16 ; The current load segment.
407 mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=0 (1-based)
408 xor dh, dh ; dh/head=0
409.the_load_loop:
410 %if 0
411 mov al, 'c'
412 call bs3PrintChrInAl
413 mov al, ch
414 call bs3PrintHexInAl
415 mov al, 's'
416 call bs3PrintChrInAl
417 mov al, cl
418 call bs3PrintHexInAl
419 mov al, 'h'
420 call bs3PrintChrInAl
421 mov al, dh
422 call bs3PrintHexInAl
423 mov al, ';'
424 call bs3PrintChrInAl
425 %elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS
426 mov al, '.'
427 call bs3PrintChrInAl
428 %endif
429 mov ax, wMaxSector ; read to the end of the side by default.
430 sub al, cl
431 inc al
432.read_again:
433 cmp si, ax
434 jae .do_read
435 mov ax, si
436.do_read:
437 mov ah, 02h ; ah=read function
438 xor bx, bx
439 mov es, di ; es:bx -> buffer
440 int 13h
441 jnc .advance_sector
442
443 cmp ah, 9 ; DMA 64KB crossing error
444 jne .failure
445 mov ax, 1 ; Retry reading a single sector.
446 jmp .read_again
447
448 ; advance to the next sector/head/cylinder and address.
449.advance_sector:
450 inc cl
451 cmp cl, bMaxSector
452 jbe .adv_addr
453
454 mov cl, 1
455 inc dh
456 cmp dh, bMaxHead
457 jbe .adv_addr
458
459 mov dh, 0
460 inc ch
461
462.adv_addr:
463 dec si
464 jz .done_reading
465 add di, 512 / 16
466 dec al
467 jnz .advance_sector
468 jmp .the_load_loop
469
470.done_reading:
471%endif ; BS3KIT_BOOTSECTOR_FASTER_LOAD
472%if 0
473 mov al, 'D'
474 call bs3PrintChrInAl
475%elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS
476 mov al, 13
477 call bs3PrintChrInAl
478 mov al, 10
479 call bs3PrintChrInAl
480%endif
481
482 add sp, 2*2
483 pop dx
484 pop es
485 pop bp
486 ret
487
488 ;
489 ; Something went wrong, display a message.
490 ;
491.failure:
492%if 1 ; Disable to save space for debugging.
493 push ax
494
495 ; print message
496 mov si, .s_szErrMsg
497.failure_next_char:
498 lodsb
499 call bs3PrintChrInAl
500 cmp si, .s_szErrMsgEnd
501 jb .failure_next_char
502
503 ; panic
504 pop ax
505 %if 1
506 mov al, ah
507 push bs3PrintHexInAl
508 %endif
509 call Bs3Panic
510.s_szErrMsg:
511 db 13, 10, 'rd err! '
512%else
513 hlt
514 jmp .failure
515%endif
516.s_szErrMsgEnd:
517;ENDPROC bs3InitLoadImage - don't want the padding.
518
519
520;
521; Pad the remainder of the sector with int3's and end it with the DOS signature.
522;
523bs3Padding:
524 times ( 510 - ( (bs3Padding - start) % 512 ) ) db 0cch
525 db 055h, 0aah
526
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