VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS/orgs.asm@ 84502

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

BIOS: Use a different heuristic for determining whether INT 19h needs to reset or not.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.6 KB
Line 
1; $Id: orgs.asm 84502 2020-05-25 14:30:24Z vboxsync $
2;; @file
3; ???
4;
5
6;
7; Copyright (C) 2006-2020 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16; --------------------------------------------------------------------
17;
18; This code is based on:
19;
20; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
21;
22; Copyright (C) 2002 MandrakeSoft S.A.
23;
24; MandrakeSoft S.A.
25; 43, rue d'Aboukir
26; 75002 Paris - France
27; http://www.linux-mandrake.com/
28; http://www.mandrakesoft.com/
29;
30; This library is free software; you can redistribute it and/or
31; modify it under the terms of the GNU Lesser General Public
32; License as published by the Free Software Foundation; either
33; version 2 of the License, or (at your option) any later version.
34;
35; This library is distributed in the hope that it will be useful,
36; but WITHOUT ANY WARRANTY; without even the implied warranty of
37; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38; Lesser General Public License for more details.
39;
40; You should have received a copy of the GNU Lesser General Public
41; License along with this library; if not, write to the Free Software
42; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
43;
44
45; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
46; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
47; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
48; a choice of LGPL license versions is made available with the language indicating
49; that LGPLv2 or any later version may be used, or where a choice of which version
50; of the LGPL is applied is otherwise unspecified.
51
52
53include commondefs.inc
54
55EBDA_SEG equ 09FC0h ; starts at 639K
56EBDA_SIZE equ 1 ; 1K
57BASE_MEM_IN_K equ (640 - EBDA_SIZE)
58
59CMOS_ADDR equ 070h
60CMOS_DATA equ 071h
61
62
63PIC_CMD_EOI equ 020h
64PIC_MASTER equ 020h
65PIC_SLAVE equ 0A0h
66
67BIOS_FIX_BASE equ 0E000h
68
69if VBOX_BIOS_CPU ge 80286
70SYS_MODEL_ID equ 0FCh ; PC/AT
71else
72SYS_MODEL_ID equ 0FBh ; PC/XT
73endif
74SYS_SUBMODEL_ID equ 0
75BIOS_REVISION equ 1
76
77BIOS_BUILD_DATE equ '06/23/99'
78BIOS_COPYRIGHT equ 'Oracle VM VirtualBox BIOS'
79
80BX_ROMBIOS32 equ 0
81BX_CALL_INT15_4F equ 1
82
83;; Set a fixed BIOS location, with a marker for verification
84BIOSORG macro addr, addr_minus_two
85.errnz (addr - 2 - addr_minus_two) ;; Couldn't convince wasm to accept $ here. Would've save us a lot of bother and ugly SED.
86 BIOSORG_CHECK_BEFORE addr_minus_two
87 org addr - BIOS_FIX_BASE - 2
88 db 'XM'
89 BIOSORG_CHECK addr
90 endm
91
92;; Set an interrupt vector (not very efficient if multiple vectors are
93;; programmed in one go)
94SET_INT_VECTOR macro vec, segm, offs
95 mov ax, offs
96 mov ds:[vec*4], ax
97 mov ax, segm
98 mov ds:[vec*4+2], ax
99endm
100
101; Set up an environment C code expects. DS must point to the BIOS segment
102; and the direction flag must be cleared(!)
103C_SETUP macro
104 push cs
105 pop ds
106 cld
107endm
108
109
110;; External function in separate modules
111extrn _dummy_isr_function:near
112extrn _log_bios_start:near
113extrn _nmi_handler_msg:near
114extrn _int18_panic_msg:near
115extrn _int09_function:near
116extrn _int13_diskette_function:near
117extrn _int13_eltorito:near
118extrn _int13_cdemu:near
119extrn _int13_cdrom:near
120extrn _cdemu_isactive:near
121extrn _cdemu_emulated_drive:near
122extrn _int13_harddisk:near
123extrn _int13_harddisk_ext:near
124extrn _int14_function:near
125extrn _int15_function:near
126extrn _int15_function_mouse:near
127extrn _int16_function:near
128extrn _int17_function:near
129extrn _int19_function:near
130extrn _int1a_function:near
131extrn _pci16_function:near
132extrn _int70_function:near
133extrn _int74_function:near
134extrn _apm_function:near
135extrn _ata_init:near
136extrn _scsi_init:near
137extrn _ata_detect:near
138extrn _cdemu_init:near
139extrn _keyboard_init:near
140extrn _print_bios_banner:near
141extrn _inv_op_handler:near
142extrn rom_scan_:near
143ifdef VBOX_WITH_AHCI
144extrn _ahci_init:near
145endif
146ifdef VBOX_WITH_VIRTIO_SCSI
147extrn _virtio_scsi_init:near
148endif
149if VBOX_BIOS_CPU ge 80286
150extrn _int15_blkmove:near
151endif
152if VBOX_BIOS_CPU ge 80386
153extrn _int15_function32:near
154extrn _apic_setup:near
155endif
156
157
158;; Symbols referenced from C code
159public _diskette_param_table
160public _pmode_IDT
161public _rmode_IDT
162public post
163public eoi_both_pics
164public rtc_post
165
166;; Additional publics for easier disassembly and debugging
167ifndef DEBUG
168 DEBUG equ 1
169endif
170ifdef DEBUG
171
172public int08_handler
173public int0e_handler
174public int11_handler
175public int12_handler
176public int13_handler
177public int13_relocated
178if VBOX_BIOS_CPU eq 8086
179public jmp_call_ret_int13_out
180endif
181public int15_handler
182public int17_handler
183public int19_handler
184public int19_relocated
185public dummy_iret
186public nmi
187public rom_fdpt
188public cpu_reset
189public normal_post
190public eoi_jmp_post
191public no_eoi_jmp_post
192public eoi_master_pic
193public ebda_post
194public seg_40_value
195public hard_drive_post
196public int13_legacy
197public int70_handler
198public int75_handler
199public int15_handler32
200public int15_handler_mouse
201public iret_modify_cf
202public init_pic
203public floppy_post
204public int13_out
205public int13_disk
206public int13_notfloppy
207public int13_legacy
208public int13_noeltorito
209public int1c_handler
210public int10_handler
211public int74_handler
212public int76_handler
213public detect_parport
214public detect_serial
215public font8x8
216
217endif
218
219;; Keyboard related constants
220KBDC_DISABLE EQU 0ADh
221KBDC_ENABLE EQU 0AEh
222KBC_CMD EQU 64h
223KBC_DATA EQU 60h
224
225
226;; NOTE: The last 8K of the ROM BIOS are peppered with fixed locations which
227;; must be retained for compatibility. As a consequence, some of the space is
228;; going to be wasted, but the gaps should be filled with miscellaneous code
229;; and data when possible.
230
231SET_DEFAULT_CPU_286
232
233BIOSSEG segment 'CODE'
234 assume cs:BIOSSEG
235
236;;
237;; Start of fixed code - eoi_jmp_post is kept near here to allow short jumps.
238;;
239 BIOSORG 0E030h, 0E02Eh
240eoi_both_pics:
241 mov al, PIC_CMD_EOI
242 out PIC_SLAVE, al
243eoi_master_pic:
244 mov al, PIC_CMD_EOI
245 out PIC_MASTER, al
246 ret
247
248 ;; routine to write the pointer in DX:AX to memory starting
249 ;; at DS:BX (repeat CX times)
250 ;; - modifies BX, CX
251set_int_vects proc near
252
253 mov [bx], ax
254 mov [bx+2], dx
255 add bx, 4
256 loop set_int_vects
257 ret
258
259set_int_vects endp
260
261eoi_jmp_post:
262;; Calling eoi_both_pics can't be done because it writes to stack, potentially
263;; corrupting memory. AT BIOS also only clears the master PIC, not both.
264 ;; clear keyboard buffer (and possible interrupt)
265 in al, KBC_DATA
266 mov al, PIC_CMD_EOI
267 out PIC_MASTER, al
268
269no_eoi_jmp_post:
270 mov ax, 40h
271 mov ds, ax
272 jmp dword ptr ds:[67h]
273
274seg_40_value: dw 40h ;; Replaces a push 40; pop ds.
275
276;; --------------------------------------------------------
277;; POST entry point
278;; --------------------------------------------------------
279 BIOSORG 0E05Bh, 0E059h
280post:
281 cli
282
283if VBOX_BIOS_CPU ge 80286
284 ;; Check if in protected (V86) mode. If so, the CPU needs
285 ;; to be reset.
286 .286p
287 smsw ax
288 test ax, 1
289 jz in_real_mode
290 SET_DEFAULT_CPU_286
291else
292 jmp in_real_mode
293endif
294
295 ;; Reset processor to get out of protected mode. Use system
296 ;; port instead of KBC.
297reset_sys:
298 mov al, 1
299 out 92h, al
300 jmp $ ; not strictly necessary in a VM
301
302
303in_real_mode:
304 ;; read the CMOS shutdown status
305 mov al, 0Fh
306 out CMOS_ADDR, al
307 in al, CMOS_DATA
308
309 ;; save status
310 xchg ah, al
311
312 ;; Check KBC self-test/shutdown flag. If it is set, we need
313 ;; to check for a reboot attempt.
314 in al, 64h
315 test al, 4 ; clear flag indicates cold boot
316 jz cont_post
317
318 ;; Warm boot, check the shutdown byte.
319 mov al, ah
320 or al, al
321 jnz cont_post
322
323 ;; Warm boot but shutdown byte is zero. This is either a warm
324 ;; boot request or an attempt to reset the system via triple
325 ;; faulting the CPU or similar. Check reboot flag.
326 ;; NB: At this point, registers need not be preserved.
327 mov ds, cs:[seg_40_value]
328 cmp word ptr ds:[72h], 1234h
329 jnz reset_sys ; trigger system reset
330
331cont_post:
332 ;; reset the shutdown status in CMOS
333 mov al, 0Fh
334 out CMOS_ADDR, al
335 mov al, 0
336 out CMOS_DATA, al
337
338 ;; pre-check the shutdown status - shutdown codes 9/A leave
339 ;; the hardware alone
340 mov al, ah
341 cmp al, 09h
342 jz check_shutdown
343 cmp al, 0Ah
344 jz check_shutdown
345
346 xor al, al
347
348 ;; reset the DMA controllers
349 out 00Dh, al
350 out 0DAh, al
351
352 ;; then initialize the DMA controllers
353 mov al, 0C0h
354 out 0D6h, al ; enable channel 4 cascade
355 mov al, 0
356 out 0D4h, al ; unmask channel 4
357
358check_shutdown:
359 ;; examine the shutdown status code
360 mov al, ah
361 cmp al, 0
362 jz normal_post
363
364 cmp al, 0Dh
365 jae normal_post
366 cmp al, 9
367 jne check_next_std
368 jmp return_blkmove
369check_next_std:
370
371 mov sp, 400h
372 ;; 05h = EOI + jump through 40:67
373 cmp al, 5
374 je eoi_jmp_post
375 ;; 0ah = jump through 40:67 (no EOI) ;ba x 1 %fe05b ; ba x 1 %18b81
376 cmp al, 0ah
377 je no_eoi_jmp_post
378
379 ;; any other shutdown status values are ignored
380 ;; OpenSolaris sets the status to 0Ah in some cases?
381 jmp normal_post
382
383normal_post:
384 ;; shutdown code 0: normal startup
385
386 ;; Set up the stack top at 0:7800h. The stack should not be
387 ;; located above 0:7C00h; that conflicts with PXE, which
388 ;; considers anything above that address to be fair game.
389 ;; The traditional locations are 30:100 (PC) or 0:400 (PC/AT).
390 mov ax, 7800h
391 mov sp, ax
392 xor ax, ax
393 mov ds, ax
394 mov ss, ax
395
396 ;; clear the bottom of memory except for the word at 40:72
397 ;; TODO: Why not clear all of it? What's the point?
398 mov es, ax
399 xor di, di
400 cld
401 mov cx, 0472h / 2
402 rep stosw
403 inc di
404 inc di
405 mov cx, (1000h - 0472h - 2) / 2
406 rep stosw
407
408 ;; clear the remaining base memory except for the top
409 ;; of the EBDA (the MP table is planted there)
410 xor bx, bx
411memory_zero_loop:
412 add bx, 1000h
413 cmp bx, 9000h
414 jae memory_cleared
415 mov es, bx
416 xor di, di
417 mov cx, 8000h ; 32K words
418 rep stosw
419 jmp memory_zero_loop
420memory_cleared:
421 mov es, bx
422 xor di, di
423 mov cx, 7FF8h ; all but the last 16 bytes
424 rep stosw
425 xor bx, bx
426
427
428 C_SETUP
429 call _log_bios_start
430
431if VBOX_BIOS_CPU ge 80386
432 call pmode_setup
433endif
434
435 ;; set all interrupts in 00h-5Fh range to default handler
436 xor bx, bx
437 mov ds, bx
438 mov cx, 60h ; leave the rest as zeros
439 mov ax, dummy_iret
440 mov dx, BIOSSEG
441 call set_int_vects
442
443 ;; also set 68h-77h to default handler; note that the
444 ;; 60h-67h range must contain zeros for certain programs
445 ;; to function correctly
446 mov bx, 68h * 4
447 mov cx, 10h
448 call set_int_vects
449
450 ;; base memory in K to 40:13
451 mov ax, BASE_MEM_IN_K
452 mov ds:[413h], ax
453
454 ;; manufacturing test at 40:12
455 ;; zeroed out above
456
457 ;; set up various service vectors
458 ;; TODO: This should use the table at FEF3h instead
459 SET_INT_VECTOR 06h, BIOSSEG, int06_handler
460 SET_INT_VECTOR 11h, BIOSSEG, int11_handler
461 SET_INT_VECTOR 12h, BIOSSEG, int12_handler
462 SET_INT_VECTOR 15h, BIOSSEG, int15_handler
463 SET_INT_VECTOR 17h, BIOSSEG, int17_handler
464 SET_INT_VECTOR 18h, BIOSSEG, int18_handler
465 SET_INT_VECTOR 19h, BIOSSEG, int19_handler
466 SET_INT_VECTOR 1Ch, BIOSSEG, int1c_handler
467
468 call ebda_post
469
470 ;; Initialize PCI devices. This can and should be done early.
471if VBOX_BIOS_CPU ge 80386 ; (Impossible to do on 16-bit CPUs.)
472 call pcibios_init_iomem_bases
473 call pcibios_init_irqs
474endif
475 SET_INT_VECTOR 1Ah, BIOSSEG, int1a_handler
476
477 ;; PIT setup
478 SET_INT_VECTOR 08h, BIOSSEG, int08_handler
479 mov al, 34h ; timer 0, binary, 16-bit, mode 2
480 out 43h, al
481 mov al, 0 ; max count -> ~18.2 Hz
482 out 40h, al
483 out 40h, al
484
485 ;; video setup - must be done before POSTing VGA ROM
486 SET_INT_VECTOR 10h, BIOSSEG, int10_handler
487
488 ;; keyboard setup
489 SET_INT_VECTOR 09h, BIOSSEG, int09_handler
490 SET_INT_VECTOR 16h, BIOSSEG, int16_handler
491
492 xor ax, ax
493 mov ds, ax
494 ;; TODO: What's the point? The BDA is zeroed already?!
495 mov ds:[417h], al ; keyboard shift flags, set 1
496 mov ds:[418h], al ; keyboard shift flags, set 2
497 mov ds:[419h], al ; keyboard Alt-numpad work area
498 mov ds:[471h], al ; keyboard Ctrl-Break flag
499 mov ds:[497h], al ; keyboard status flags 4
500 mov al, 10h
501 mov ds:[496h], al ; keyboard status flags 3
502
503 mov bx, 1Eh
504 mov ds:[41Ah], bx ; keyboard buffer head
505 mov ds:[41Ch], bx ; keyboard buffer tail
506 mov ds:[480h], bx ; keyboard buffer start
507 mov bx, 3Eh
508 mov ds:[482h], bx ; keyboard buffer end
509
510 ;; store CMOS equipment byte in BDA
511 mov al, 14h
512 out CMOS_ADDR, al
513 in al, CMOS_DATA
514 mov ds:[410h], al
515
516 push ds
517 C_SETUP
518
519 ;; Scan for video ROMs in the C000-C800 range. This is done
520 ;; early so that errors are displayed on the screen.
521 mov ax, 0C000h
522 mov dx, 0C800h
523 call rom_scan_
524
525 ;; Initialize the keyboard
526 call _keyboard_init
527 pop ds
528
529 ;; parallel setup
530 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_iret
531 xor ax, ax
532 mov ds, ax
533 xor bx, bx
534 mov cl, 14h ; timeout value
535 mov dx, 378h ; parallel port 1
536 call detect_parport
537 mov dx, 278h ; parallel port 2
538 call detect_parport
539 DO_shl bx, 0Eh
540 mov ax, ds:[410h] ; equipment word
541 and ax, 3FFFh
542 or ax, bx ; set number of parallel ports
543 mov ds:[410h], ax ; store in BDA
544
545 ;; Serial setup
546 SET_INT_VECTOR 0Bh, BIOSSEG, dummy_isr ; IRQ 3
547 SET_INT_VECTOR 0Ch, BIOSSEG, dummy_isr ; IRQ 4
548 SET_INT_VECTOR 14h, BIOSSEG, int14_handler
549 xor bx, bx
550 mov cl, 0Ah ; timeout value
551 mov dx, 3F8h ; first serial address
552 call detect_serial
553 mov dx, 2F8h ; second serial address
554 call detect_serial
555 mov dx, 3E8h ; third serial address
556 call detect_serial
557 mov dx, 2E8h ; fourth serial address
558 call detect_serial
559 DO_shl bx, 9
560 mov ax, ds:[410h] ; equipment word
561 and ax, 0F1FFh ; bits 9-11 determine serial ports
562 or ax, bx
563 mov ds:[410h], ax
564
565 ;; CMOS RTC
566 SET_INT_VECTOR 4Ah, BIOSSEG, dummy_iret ; TODO: redundant?
567 SET_INT_VECTOR 70h, BIOSSEG, int70_handler
568 ;; BIOS DATA AREA 4CEh ???
569 call rtc_post
570
571 jmp norm_post_cont
572
573
574;; --------------------------------------------------------
575;; NMI handler
576;; --------------------------------------------------------
577 BIOSORG 0E2C3h, 0E2C1h
578nmi:
579 C_SETUP
580 call _nmi_handler_msg
581 iret
582
583int75_handler:
584 out 0F0h, al ; clear IRQ13
585 call eoi_both_pics
586 int 2 ; emulate legacy NMI
587 iret
588
589
590hard_drive_post proc near
591
592 xor ax, ax
593 mov ds, ax
594 ;; TODO: Didn't we just clear the entire EBDA?
595 mov ds:[474h], al ; last HD operation status
596 mov ds:[477h], al ; HD port offset (XT only???)
597 mov ds:[48Ch], al ; HD status register
598 mov ds:[48Dh], al ; HD error register
599 mov ds:[48Eh], al ; HD task complete flag
600 mov al, 0C0h
601 mov ds:[476h], al ; HD control byte
602 ;; set up hard disk interrupt vectors
603 SET_INT_VECTOR 13h, BIOSSEG, int13_handler
604 SET_INT_VECTOR 76h, BIOSSEG, int76_handler
605 ;; The ATA init code sets up INT 41h/46h FDPT pointers
606 ret
607
608hard_drive_post endp
609
610
611norm_post_cont:
612 ;; PS/2 mouse setup
613 SET_INT_VECTOR 74h, BIOSSEG, int74_handler
614
615 ;; IRQ 13h (FPU exception) setup
616 SET_INT_VECTOR 75h, BIOSSEG, int75_handler
617
618 call init_pic
619
620 C_SETUP
621
622if VBOX_BIOS_CPU ge 80386
623 ;; Set up local APIC
624 .386
625 pushad
626 call _apic_setup
627 popad
628 SET_DEFAULT_CPU_286
629endif
630
631 ;; ATA/ATAPI driver setup
632 call _ata_init
633 call _ata_detect
634
635ifdef VBOX_WITH_AHCI
636 ; AHCI driver setup
637 ;; TODO: AHCI initialization needs timer, but enabling
638 ;; interrupts elsewhere may be risky. Just do it around
639 ;; the AHCI init.
640 sti
641 call _ahci_init
642 cli
643endif
644
645ifdef VBOX_WITH_SCSI
646 ; SCSI driver setup
647 call _scsi_init
648endif
649
650ifdef VBOX_WITH_VIRTIO_SCSI
651 ; VirtIO-SCSI driver setup
652 call _virtio_scsi_init
653endif
654
655 ;; floppy setup
656 call floppy_post
657
658 ;; hard drive setup
659 call hard_drive_post
660
661 C_SETUP ; in case assembly code changed things
662 ;; Scan for additional ROMs in the C800-EFFF range
663 mov ax, 0C800h
664 mov dx, 0F000h
665 call rom_scan_
666
667if VBOX_BIOS_CPU ge 80386
668 ;; The POST code does not bother preserving high bits of the
669 ;; 32-bit registers. Now is a good time to clear them so that
670 ;; there's no garbage left in high bits.
671 .386
672 xor eax, eax
673 xor ebx, ebx
674 xor ecx, ecx
675 xor edx, edx
676 .286
677endif
678
679 call _print_bios_banner
680
681 ;; El Torito floppy/hard disk emulation
682 call _cdemu_init
683
684 ; TODO: what's the point of enabling interrupts here??
685 sti ; enable interrupts
686 int 19h
687 ;; does not return here
688 sti
689wait_forever:
690 hlt
691 jmp wait_forever
692 cli
693 hlt
694
695
696;;
697;; Return from block move (shutdown code 09h). Care must be taken to disturb
698;; register and memory state as little as possible.
699;;
700return_blkmove:
701 .286p
702 mov ax, 40h
703 mov ds, ax
704 ;; restore user stack
705 mov ss, ds:[69h]
706 mov sp, ds:[67h]
707 ;; reset A20 gate
708 in al, 92h
709 and al, 0FDh
710 out 92h, al
711 ;; ensure proper real mode IDT
712 lidt fword ptr cs:_rmode_IDT
713 ;; restore user segments
714 pop ds
715 pop es
716 ;; set up BP
717 mov bp, sp
718 ;; restore status code
719 in al, 80h
720 mov [bp+15], al
721 ;; set ZF/CF
722 cmp ah,al ; AH is zero here!
723 ;; restore registers and return
724 popa
725 sti
726 retf 2
727 SET_DEFAULT_CPU_286
728
729
730;; --------------------------------------------------------
731;; INT 13h handler - Disk services
732;; --------------------------------------------------------
733 BIOSORG 0E3FEh, 0E3FCh
734
735int13_handler:
736 jmp int13_relocated
737
738
739;; --------------------------------------------------------
740;; Fixed Disk Parameter Table
741;; --------------------------------------------------------
742 BIOSORG_CHECK 0E401h ; fixed wrt preceding
743
744rom_fdpt:
745
746;; --------------------------------------------------------
747;; INT 19h handler - Boot load service
748;; --------------------------------------------------------
749 BIOSORG 0E6F2h, 0E6F0h
750
751int19_handler:
752 jmp int19_relocated
753
754
755
756;; --------------------------------------------------------
757;; System BIOS Configuration Table
758;; --------------------------------------------------------
759 BIOSORG_CHECK 0E6F5h ; fixed wrt preceding
760; must match BIOS_CONFIG_TABLE
761bios_cfg_table:
762 dw 9 ; table size in bytes
763 db SYS_MODEL_ID
764 db SYS_SUBMODEL_ID
765 db BIOS_REVISION
766 ; Feature byte 1
767 ; b7: 1=DMA channel 3 used by hard disk
768 ; b6: 1=2 interrupt controllers present
769 ; b5: 1=RTC present
770 ; b4: 1=BIOS calls int 15h/4Fh for every key
771 ; b3: 1=wait for extern event supported (Int 15h/41h)
772 ; b2: 1=extended BIOS data area used
773 ; b1: 0=AT or ESDI bus, 1=MicroChannel
774 ; b0: 1=Dual bus (MicroChannel + ISA)
775ifdef BX_CALL_INT15_4F
776 db 74h; or USE_EBDA
777else
778 db 64h; or USE_EBDA
779endif
780 ; Feature byte 2
781 ; b7: 1=32-bit DMA supported
782 ; b6: 1=int16h, function 9 supported
783 ; b5: 1=int15h/C6h (get POS data) supported
784 ; b4: 1=int15h/C7h (get mem map info) supported
785 ; b3: 1=int15h/C8h (en/dis CPU) supported
786 ; b2: 1=non-8042 kb controller
787 ; b1: 1=data streaming supported
788 ; b0: reserved
789 db 40h
790 ; Feature byte 3
791 ; b7: not used
792 ; b6: reserved
793 ; b5: reserved
794 ; b4: POST supports ROM-to-RAM enable/disable
795 ; b3: SCSI on system board
796 ; b2: info panel installed
797 ; b1: Initial Machine Load (IML) system - BIOS on disk
798 ; b0: SCSI supported in IML
799 db 0
800 ; Feature byte 4
801 ; b7: IBM private
802 ; b6: EEPROM present
803 ; b5-3: ABIOS presence (011 = not supported)
804 ; b2: private
805 ; b1: memory split above 16Mb supported
806 ; b0: POSTEXT directly supported by POST
807 db 0
808 ; Feature byte 5 (IBM)
809 ; b1: enhanced mouse
810 ; b0: flash EPROM
811 db 0
812
813
814;; --------------------------------------------------------
815;; Baud Rate Generator Table
816;; --------------------------------------------------------
817 BIOSORG 0E729h, 0E727h
818
819
820;; --------------------------------------------------------
821;; INT 14h handler - Serial Communication Service
822;; --------------------------------------------------------
823 BIOSORG 0E739h, 0E737h
824int14_handler:
825 push ds
826 push es
827 DO_pusha
828 C_SETUP
829 call _int14_function
830 DO_popa
831 pop es
832 pop ds
833 iret
834
835
836
837;;
838;; Handler for unexpected hardware interrupts
839;;
840dummy_isr:
841 push ds
842 push es
843 DO_pusha
844 C_SETUP
845 call _dummy_isr_function
846 DO_popa
847 pop es
848 pop ds
849 iret
850
851
852init_pic proc near
853
854 mov al, 11h ; send init commands
855 out PIC_MASTER, al
856 out PIC_SLAVE, al
857 mov al, 08h ; base 08h
858 out PIC_MASTER+1, al
859 mov al, 70h ; base 70h
860 out PIC_SLAVE+1, al
861 mov al, 04h ; master PIC
862 out PIC_MASTER+1, al
863 mov al, 02h ; slave PIC
864 out PIC_SLAVE+1, al
865 mov al, 01h
866 out PIC_MASTER+1, al
867 out PIC_SLAVE+1, al
868 mov al, 0B8h ; unmask IRQs 0/1/2/6
869 out PIC_MASTER+1, al
870 mov al, 08Fh
871 out PIC_SLAVE+1, al ; unmask IRQs 12/13/14
872 ret
873
874init_pic endp
875
876ebda_post proc near
877
878 SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
879 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
880 SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 10
881 SET_INT_VECTOR 73h, BIOSSEG, dummy_isr ; IRQ 11
882 SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
883
884 mov ax, EBDA_SEG
885 mov ds, ax
886 mov byte ptr ds:[0], EBDA_SIZE
887 ;; store EBDA seg in 40:0E
888 xor ax, ax
889 mov ds, ax
890 mov word ptr ds:[40Eh], EBDA_SEG
891 ret
892
893ebda_post endp
894
895
896
897;; --------------------------------------------------------
898;; INT 16h handler - Keyboard service
899;; --------------------------------------------------------
900 BIOSORG 0E82Eh, 0E82Ch
901int16_handler:
902 sti
903 ;; Flags are saved *after* enabling interrupts, and with
904 ;; implicitly cleared TF. Software may depend on that.
905 pushf
906 push es
907 push ds
908 DO_pusha
909
910 cmp ah, 0
911 je int16_F00
912
913 cmp ah, 10h
914 je int16_F00
915
916 C_SETUP
917 call _int16_function
918 DO_popa
919 pop ds
920 pop es
921 add sp, 2 ; Skip saved flags
922 iret
923
924int16_F00:
925 mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
926 mov ds, bx
927int16_wait_for_key:
928 cli
929 mov bx, ds:[1Ah]
930 cmp bx, ds:[1Ch]
931 jne int16_key_found
932 sti
933 nop
934; TODO: review/enable?
935if 0
936 push ax
937 mov ax, 9002h
938 int 15h
939 pop ax
940endif
941 jmp int16_wait_for_key
942
943int16_key_found:
944 C_SETUP
945 call _int16_function
946 DO_popa
947 pop ds
948 pop es
949 add sp, 2 ; Skip saved flags
950; TODO: review/enable? If so, flags should be restored here?
951if 0
952 push ax
953 mov ax, 9202h
954 int 15h
955 pop ax
956endif
957 iret
958
959
960if VBOX_BIOS_CPU ge 80386
961;; Quick and dirty protected mode entry/exit routines
962include pmode.inc
963
964;; Initialization code which needs to run in protected mode (LAPIC etc.)
965include pmsetup.inc
966endif
967
968
969;; --------------------------------------------------------
970;; INT 09h handler - Keyboard ISR (IRQ 1)
971;; --------------------------------------------------------
972 BIOSORG 0E987h, 0E985h
973int09_handler:
974 cli ; TODO: why? they're off already!
975 push ax
976 mov al, KBDC_DISABLE
977 out KBC_CMD, al
978
979 in al, KBC_DATA
980 push ds
981 DO_pusha
982 cld ; Before INT 15h (and any C code)
983ifdef BX_CALL_INT15_4F
984 mov ah, 4Fh
985 stc
986 int 15h ; keyboard intercept
987 jnc int09_done
988endif
989 sti ; Only after calling INT 15h
990
991 ;; check for extended key
992 cmp al, 0E0h
993 jne int09_check_pause
994 xor ax, ax
995 mov ds, ax
996 or byte ptr ds:[496h], 2 ; mf2_state |= 0x02
997 jmp int09_done
998
999int09_check_pause:
1000 cmp al, 0E1h ; pause key?
1001 jne int09_process_key
1002 xor ax, ax
1003 mov ds, ax
1004 or byte ptr ds:[496h], 1 ; mf2_state | 0x01
1005 jmp int09_done
1006
1007int09_process_key:
1008 push es
1009 C_SETUP
1010 call _int09_function
1011 pop es
1012
1013int09_done:
1014 DO_popa
1015 pop ds
1016 cli
1017 call eoi_master_pic
1018
1019 mov al, KBDC_ENABLE
1020 out KBC_CMD, al
1021 pop ax
1022 iret
1023
1024
1025;; --------------------------------------------------------
1026;; INT 06h handler - Invalid Opcode Exception
1027;; --------------------------------------------------------
1028
1029int06_handler:
1030 DO_pusha
1031 push es
1032 push ds
1033 C_SETUP
1034 call _inv_op_handler
1035 pop ds
1036 pop es
1037 DO_popa
1038 iret
1039
1040;; --------------------------------------------------------
1041;; INT 13h handler - Diskette service
1042;; --------------------------------------------------------
1043 BIOSORG 0EC59h, 0EC57h
1044int13_diskette:
1045 jmp int13_noeltorito
1046
1047
1048
1049;; --------------------------------------------------------
1050;; INT 13h handler - Disk service
1051;; --------------------------------------------------------
1052int13_relocated:
1053 ;; check for an El-Torito function
1054 cmp ah, 4Ah
1055 jb int13_not_eltorito
1056
1057 cmp ah, 4Dh
1058 ja int13_not_eltorito
1059
1060 DO_pusha
1061 push es
1062 push ds
1063 C_SETUP ; TODO: setup C envrionment only once?
1064 DO_JMP_CALL_EX _int13_eltorito, int13_out, jmp_call_ret_int13_out ; ELDX not used
1065if VBOX_BIOS_CPU eq 8086
1066jmp_call_ret_int13_out: dw offset int13_out
1067endif
1068
1069int13_not_eltorito:
1070 push es
1071 push ax ; TODO: better register save/restore
1072 push bx
1073 push cx
1074 push dx
1075
1076 ;; check if emulation is active
1077 call _cdemu_isactive
1078 cmp al, 0
1079 je int13_cdemu_inactive
1080
1081 ;; check if access to the emulated drive
1082 call _cdemu_emulated_drive
1083 pop dx ; recover dx (destroyed by C code)
1084 push dx
1085 cmp al, dl ; INT 13h on emulated drive
1086 jne int13_nocdemu
1087
1088 pop dx
1089 pop cx
1090 pop bx
1091 pop ax
1092 pop es
1093
1094 DO_pusha
1095 push es
1096 push ds
1097 C_SETUP ; TODO: setup environment only once?
1098
1099 DO_JMP_CALL_EX _int13_cdemu, int13_out, jmp_call_ret_int13_out ; ELDX not used
1100
1101int13_nocdemu:
1102 and dl, 0E0h ; mask to get device class
1103 cmp al, dl
1104 jne int13_cdemu_inactive
1105
1106 pop dx
1107 pop cx
1108 pop bx
1109 pop ax
1110 pop es
1111
1112 push ax
1113 push cx
1114 push dx
1115 push bx
1116
1117 dec dl ; real drive is dl - 1
1118 jmp int13_legacy
1119
1120int13_cdemu_inactive:
1121 pop dx
1122 pop cx
1123 pop bx
1124 pop ax
1125 pop es
1126
1127int13_noeltorito:
1128 push ax
1129 push cx
1130 push dx
1131 push bx
1132int13_legacy:
1133 push dx ; push eltorito dx in place of sp
1134 push bp
1135 push si
1136 push di
1137 push es
1138 push ds
1139 C_SETUP ; TODO: setup environment only once?
1140
1141 ;; now the registers can be restored with
1142 ;; pop ds; pop es; DO_popa; iret
1143 test dl, 80h ; non-removable?
1144 jnz int13_notfloppy
1145
1146 DO_JMP_CALL_EX _int13_diskette_function, int13_out, jmp_call_ret_int13_out
1147
1148int13_notfloppy:
1149 cmp dl, 0E0h
1150 jb int13_notcdrom
1151
1152 ;; ebx may be modified, save here
1153 ;; TODO: check/review 32-bit register use
1154 ;; @todo figure if 80286/8086 variant is applicable.
1155 .386
1156 shr ebx, 16
1157 push bx
1158 call _int13_cdrom
1159 pop bx
1160 shl ebx, 16
1161 SET_DEFAULT_CPU_286
1162 jmp int13_out
1163
1164int13_notcdrom:
1165int13_disk:
1166 cmp ah,40h
1167 ja int13x
1168 call _int13_harddisk
1169 jmp int13_out
1170
1171int13x:
1172 call _int13_harddisk_ext
1173
1174int13_out:
1175 pop ds
1176 pop es
1177 DO_popa
1178 iret
1179
1180
1181
1182; parallel port detection: port in dx, index in bx, timeout in cl
1183detect_parport proc near
1184
1185 push dx
1186 inc dx
1187 inc dx
1188 in al, dx
1189 and al, 0DFh ; clear input mode
1190 out dx, al
1191 pop dx
1192 mov al, 0AAh
1193 out dx, al
1194 in al, dx
1195 cmp al, 0AAh
1196 jne no_parport
1197
1198 push bx
1199 shl bx, 1
1200 mov [bx+408h], dx ; parallel I/O address
1201 pop bx
1202 mov [bx+478h], cl ; parallel printer timeout
1203 inc bx
1204no_parport:
1205 ret
1206
1207detect_parport endp
1208
1209; setial port detection: port in dx, index in bx, timeout in cl
1210detect_serial proc near
1211
1212 push dx
1213 inc dx
1214 mov al, 2
1215 out dx, al
1216 in al, dx
1217 cmp al, 2
1218 jne no_serial
1219
1220 inc dx
1221 in al, dx
1222 cmp al, 2
1223 jne no_serial
1224
1225 dec dx
1226 xor al, al
1227 pop dx
1228 push bx
1229 shl bx, 1
1230 mov [bx+400h], dx ; serial I/O address
1231 pop bx
1232 mov [bx+47Ch], cl ; serial timeout
1233 inc bx
1234 ret
1235
1236no_serial:
1237 pop dx
1238 ret
1239
1240detect_serial endp
1241
1242
1243;;
1244;; POST: Floppy drive
1245;;
1246floppy_post proc near
1247
1248 xor ax, ax
1249 mov ds, ax
1250
1251 ;; TODO: This code is really stupid. Zeroing the BDA byte
1252 ;; by byte is dumb, and it's been already zeroed elsewhere!
1253 mov al, 0
1254 mov ds:[43Eh], al ; drive 0/1 uncalibrated, no IRQ
1255 mov ds:[43Fh], al ; motor status
1256 mov ds:[440h], al ; motor timeout counter
1257 mov ds:[441h], al ; controller status return code
1258 mov ds:[442h], al ; hd/floppy ctlr status register
1259 mov ds:[443h], al ; controller status register 1
1260 mov ds:[444h], al ; controller status register 2
1261 mov ds:[445h], al ; cylinder number
1262 mov ds:[446h], al ; head number
1263 mov ds:[447h], al ; sector number
1264 mov ds:[448h], al ; bytes written
1265
1266 mov ds:[48Bh], al ; configuration data
1267
1268 mov al, 10h ; floppy drive type
1269 out CMOS_ADDR, al
1270 in al, CMOS_DATA
1271 mov ah, al ; save drive type byte
1272
1273look_drive0:
1274 ; TODO: pre-init bl to reduce jumps
1275 DO_shr al, 4 ; drive 0 in high nibble
1276 jz f0_missing ; jump if no drive
1277 mov bl, 7 ; drv0 determined, multi-rate, chgline
1278 jmp look_drive1
1279
1280f0_missing:
1281 mov bl, 0 ; no drive 0
1282
1283look_drive1:
1284 mov al, ah ; restore CMOS data
1285 and al, 0Fh ; drive 1 in low nibble
1286 jz f1_missing
1287 or bl, 70h ; drv1 determined, multi-rate, chgline
1288f1_missing:
1289 mov ds:[48Fh], bl ; store in BDA
1290
1291 ;; TODO: See above. Dumb *and* redundant!
1292 mov al, 0
1293 mov ds:[490h], al ; drv0 media state
1294 mov ds:[491h], al ; drv1 media state
1295 mov ds:[492h], al ; drv0 operational state
1296 mov ds:[493h], al ; drv1 operational state
1297 mov ds:[494h], al ; drv0 current cylinder
1298 mov ds:[495h], al ; drv1 current cylinder
1299
1300 mov al, 2
1301 out 0Ah, al ; unmask DMA channel 2
1302
1303 SET_INT_VECTOR 1Eh, BIOSSEG, _diskette_param_table
1304 SET_INT_VECTOR 40h, BIOSSEG, int13_diskette
1305 SET_INT_VECTOR 0Eh, BIOSSEG, int0e_handler ; IRQ 6
1306
1307 ret
1308
1309floppy_post endp
1310
1311
1312bcd_to_bin proc near
1313
1314 ;; in : AL in packed BCD format
1315 ;; out: AL in binary, AH always 0
1316if VBOX_BIOS_CPU ge 80186
1317 shl ax, 4
1318 shr al, 4
1319else
1320 push cx
1321 mov cl, 4
1322 shl ax, cl
1323 shr al, cl
1324 pop cx
1325endif
1326 aad
1327 ret
1328
1329bcd_to_bin endp
1330
1331rtc_post proc near
1332
1333if VBOX_BIOS_CPU lt 80386 ;; @todo fix loopy code below
1334 ;; get RTC seconds
1335 mov al, 0
1336 out CMOS_ADDR, al
1337 in al, CMOS_DATA ; RTC seconds, in BCD
1338 call bcd_to_bin ; ax now has seconds in binary
1339 test al, al
1340 xor ah, ah
1341 mov dx, 0x1234 ; 18206507*0x100/1000000 = 0x1234 (4660.865792)
1342 mul dx
1343 mov cx, ax ; tick count in dx:cx
1344
1345 ;; get RTC minutes
1346 mov al, 2
1347 out CMOS_ADDR, al
1348 in al, CMOS_DATA ; RTC minutes, in BCD
1349 call bcd_to_bin ; eax now has minutes in binary
1350 test al, al
1351 jz rtc_post_hours
1352rtc_pos_min_loop: ; 18206507*60*0x100/1000000 = 0x44463 (279651.94752)
1353 add cx, 0x4463
1354 adc dx, 0x0004
1355 dec al
1356 jnz rtc_pos_min_loop
1357
1358 ;; get RTC hours
1359rtc_post_hours:
1360 mov al, 4
1361 out CMOS_ADDR, al
1362 in al, CMOS_DATA ; RTC hours, in BCD
1363 call bcd_to_bin ; eax now has hours in binary
1364 test al, al
1365 jz rtc_pos_shift
1366rtc_pos_hour_loop: ; 18206507*3600*0x100/1000000 = 0x100076C (16779116.8512)
1367 add cx, 0x076C
1368 adc dx, 0x0100
1369 dec al
1370 jnz rtc_pos_hour_loop
1371
1372rtc_pos_shift:
1373 mov cl, ch
1374 mov ch, dl
1375 mov dl, dh
1376 xor dh, dh
1377 mov ds:[46Ch], cx ; timer tick count
1378 mov ds:[46Ch+2], dx ; timer tick count
1379 mov ds:[470h], dh ; rollover flag
1380
1381else
1382 .386
1383 ;; get RTC seconds
1384 xor eax, eax
1385 mov al, 0
1386 out CMOS_ADDR, al
1387 in al, CMOS_DATA ; RTC seconds, in BCD
1388 call bcd_to_bin ; eax now has seconds in binary
1389 mov edx, 18206507
1390 mul edx
1391 mov ebx, 1000000
1392 xor edx, edx
1393 div ebx
1394 mov ecx, eax ; total ticks in ecx
1395
1396 ;; get RTC minutes
1397 xor eax, eax
1398 mov al, 2
1399 out CMOS_ADDR, al
1400 in al, CMOS_DATA ; RTC minutes, in BCD
1401 call bcd_to_bin ; eax now has minutes in binary
1402 mov edx, 10923904
1403 mul edx
1404 mov ebx, 10000
1405 xor edx, edx
1406 div ebx
1407 add ecx, eax ; add to total ticks
1408
1409 ;; get RTC hours
1410 xor eax, eax
1411 mov al, 4
1412 out CMOS_ADDR, al
1413 in al, CMOS_DATA ; RTC hours, in BCD
1414 call bcd_to_bin ; eax now has hours in binary
1415 mov edx, 65543427
1416 mul edx
1417 mov ebx, 1000
1418 xor edx, edx
1419 div ebx
1420 add ecx, eax ; add to total ticks
1421
1422 mov ds:[46Ch], ecx ; timer tick count
1423 xor al, al ; TODO: redundant?
1424 mov ds:[470h], al ; rollover flag
1425 .286
1426endif
1427 ret
1428
1429rtc_post endp
1430
1431
1432
1433;; --------------------------------------------------------
1434;; INT 0Eh handler - Diskette IRQ 6 ISR
1435;; --------------------------------------------------------
1436 BIOSORG 0EF57h, 0EF55h
1437int0e_handler:
1438 push ax
1439 push dx
1440 mov dx, 3F4h
1441 in al, dx
1442 and al, 0C0h
1443 cmp al, 0C0h
1444 je int0e_normal
1445 mov dx, 3F5h
1446 mov al, 08h ; sense interrupt
1447 out dx, al
1448int0e_loop1:
1449 mov dx, 3F4h ; TODO: move out of the loop?
1450 in al, dx
1451 and al, 0C0h
1452 cmp al, 0C0h
1453 jne int0e_loop1
1454
1455int0e_loop2:
1456 mov dx, 3F5h ; TODO: inc/dec dx instead
1457 in al, dx
1458 mov dx, 3F4h
1459 in al, dx
1460 and al, 0C0h
1461 cmp al, 0C0h
1462 je int0e_loop2
1463
1464int0e_normal:
1465 push ds
1466 xor ax, ax
1467 mov ds, ax
1468 call eoi_master_pic
1469 ; indicate that an interrupt occurred
1470 or byte ptr ds:[43Eh], 80h
1471 pop ds
1472 pop dx
1473 pop ax
1474 iret
1475
1476
1477;; --------------------------------------------------------
1478;; Diskette Parameter Table
1479;; --------------------------------------------------------
1480 BIOSORG 0EFC7h, 0EFC5h
1481_diskette_param_table:
1482 db 0AFh
1483 db 2 ; HLT=1, DMA mode
1484 db 025h
1485 db 2
1486 db 18 ; SPT (good for 1.44MB media)
1487 db 01Bh
1488 db 0FFh
1489 db 06Ch
1490 db 0F6h ; format filler
1491 db 15
1492 db 8
1493
1494
1495
1496;; --------------------------------------------------------
1497;; INT 17h handler - Printer service
1498;; --------------------------------------------------------
1499 BIOSORG_CHECK 0EFD2h ; fixed WRT preceding code
1500
1501 jmp int17_handler ; NT floppy boot workaround
1502 ; see @bugref{6481}
1503int17_handler:
1504 push ds
1505 push es
1506 DO_pusha
1507 C_SETUP
1508 call _int17_function
1509 DO_popa
1510 pop es
1511 pop ds
1512 iret
1513
1514
1515
1516;; Protected mode IDT descriptor
1517;;
1518;; The limit is 0 to cause a shutdown if an exception occurs
1519;; in protected mode. TODO: Is that what we really want?
1520;;
1521;; Set base to F0000 to correspond to beginning of BIOS,
1522;; in case an IDT is defined later.
1523
1524_pmode_IDT:
1525 dw 0 ; limit 15:0
1526 dw 0 ; base 15:0
1527 dw 0Fh ; base 23:16
1528
1529
1530;; Real mode IDT descriptor
1531;;
1532;; Set to typical real-mode values.
1533;; base = 000000
1534;; limit = 03ff
1535
1536_rmode_IDT:
1537 dw 3FFh ; limit 15:00
1538 dw 0 ; base 15:00
1539 dw 0 ; base 23:16
1540
1541
1542;;
1543;; INT 1Ch
1544;;
1545;; TODO: Why does this need a special handler?
1546int1c_handler: ;; user timer tick
1547 iret
1548
1549
1550
1551;; --------------------------------------------------------
1552;; INT 10h functions 0-Fh entry point
1553;; --------------------------------------------------------
1554 BIOSORG 0F045h, 0F043h
1555i10f0f_entry:
1556 iret
1557
1558
1559;; --------------------------------------------------------
1560;; INT 10h handler - MDA/CGA video
1561;; --------------------------------------------------------
1562 BIOSORG 0F065h, 0F063h
1563int10_handler:
1564 ;; do nothing - assumes VGA
1565 iret
1566
1567
1568;; --------------------------------------------------------
1569;; MDA/CGA Video Parameter Table (INT 1Dh)
1570;; --------------------------------------------------------
1571 BIOSORG 0F0A4h, 0F0A2h
1572mdacga_vpt:
1573
1574
1575;;
1576;; INT 18h - boot failure
1577;;
1578int18_handler:
1579 C_SETUP
1580 call _int18_panic_msg
1581 ;; TODO: handle failure better?
1582 hlt
1583 iret
1584
1585;;
1586;; INT 19h - boot service - relocated
1587;;
1588int19_relocated:
1589; If an already booted OS calls int 0x19 to reboot, it is not sufficient
1590; just to try booting from the configured drives. All BIOS variables and
1591; interrupt vectors need to be reset, otherwise strange things may happen.
1592; The approach used is faking a warm reboot (which just skips showing the
1593; logo), which is a bit more than what we need, but hey, it's fast.
1594;
1595; Initially we checked if the caller is in the F000h segment, i.e. the
1596; system BIOS. But option ROMs can also legitimately invoke INT 19h so
1597; we need different heuristics.
1598 xor ax, ax
1599 mov ds, ax
1600 mov es, ax
1601 cld
1602 ; Check if the boot sector area is untouched
1603 mov cx, 256
1604 mov di, 7C00h
1605 repe scasw
1606 jcxz bios_initiated_boot
1607
1608 mov ax, 1234h
1609 mov ds:[472], ax
1610 jmp post
1611
1612bios_initiated_boot:
1613 ;; The C worker function returns the boot drive in bl and
1614 ;; the boot segment in ax. In case of failure, the boot
1615 ;; segment will be zero.
1616 C_SETUP ; TODO: Here? Now?
1617 push bp
1618 mov bp, sp
1619
1620 ;; 1st boot device
1621 mov ax, 1
1622 push ax
1623 call _int19_function
1624 inc sp
1625 inc sp
1626 test ax, ax ; if 0, try next device
1627 jnz boot_setup
1628
1629 ;; 2nd boot device
1630 mov ax, 2
1631 push ax
1632 call _int19_function
1633 inc sp
1634 inc sp
1635 test ax, ax ; if 0, try next device
1636 jnz boot_setup
1637
1638 ; 3rd boot device
1639 mov ax, 3
1640 push ax
1641 call _int19_function
1642 inc sp
1643 inc sp
1644 test ax, ax ; if 0, try next device
1645 jnz boot_setup
1646
1647 ; 4th boot device
1648 mov ax, 4
1649 push ax
1650 call _int19_function
1651 inc sp
1652 inc sp
1653 test ax, ax ; if 0, invoke INT 18h
1654 jz int18_handler
1655
1656boot_setup:
1657; TODO: the drive should be in dl already??
1658;; mov dl, bl ; tell guest OS what boot drive is
1659if VBOX_BIOS_CPU lt 80386
1660 mov [bp], ax
1661 DO_shl ax, 4
1662 mov [bp+2], ax ; set ip
1663 mov ax, [bp]
1664else
1665 .386 ; NB: We're getting garbage into high eax bits
1666 shl eax, 4 ; convert seg to ip
1667 mov [bp+2], ax ; set ip
1668
1669 shr eax, 4 ; get cs back
1670 .286
1671endif
1672 and ax, BIOSSEG ; remove what went in ip
1673 mov [bp+4], ax ; set cs
1674 xor ax, ax
1675 mov ds, ax
1676 mov es, ax
1677 mov [bp], ax ; TODO: what's this?!
1678 mov ax, 0AA55h ; set ok flag ; TODO: and this?
1679
1680 pop bp ; TODO: why'd we just zero it??
1681 iret ; beam me up scotty
1682
1683;; PCI BIOS
1684
1685include pcibios.inc
1686include pirq.inc
1687
1688
1689;; --------------------------------------------------------
1690;; INT 12h handler - Memory size
1691;; --------------------------------------------------------
1692 BIOSORG 0F841h, 0F83Fh
1693int12_handler:
1694 ;; Don't touch - fixed size!
1695 sti
1696 push ds
1697 mov ax, 40h
1698 mov ds, ax
1699 mov ax, ds:[13h]
1700 pop ds
1701 iret
1702
1703
1704;; --------------------------------------------------------
1705;; INT 11h handler - Equipment list service
1706;; --------------------------------------------------------
1707 BIOSORG_CHECK 0F84Dh ; fixed wrt preceding code
1708int11_handler:
1709 ;; Don't touch - fixed size!
1710 sti
1711 push ds
1712 mov ax, 40h
1713 mov ds, ax
1714 mov ax, ds:[10h]
1715 pop ds
1716 iret
1717
1718
1719;; --------------------------------------------------------
1720;; INT 15h handler - System services
1721;; --------------------------------------------------------
1722 BIOSORG_CHECK 0F859h ; fixed wrt preceding code
1723int15_handler:
1724
1725if VBOX_BIOS_CPU ge 80286
1726 cmp ah, 87h
1727 jne not_blkmove
1728
1729 ;; INT 15h/87h has semi-public interface because software
1730 ;; may use CMOS shutdown status code 9 for its own purposes.
1731 ;; The stack layout has to match.
1732 pusha
1733 push es
1734 push ds
1735 C_SETUP
1736 call _int15_blkmove
1737 pop ds
1738 pop es
1739 popa
1740 iret
1741not_blkmove:
1742
1743endif
1744
1745 pushf
1746 push ds
1747 push es
1748 C_SETUP
1749if VBOX_BIOS_CPU ge 80386
1750 ;; int15_function32 exists in 386+ BIOS only, but INT 15h is
1751 ;; not 386-specific
1752 cmp ah, 0E8h
1753 je int15_handler32
1754 cmp ah, 0d0h
1755 je int15_handler32
1756endif
1757 DO_pusha
1758 cmp ah, 53h ; APM function?
1759 je apm_call
1760 cmp ah, 0C2h ; PS/2 mouse function?
1761 je int15_handler_mouse
1762
1763 call _int15_function
1764int15_handler_popa_ret:
1765 DO_popa
1766if VBOX_BIOS_CPU ge 80386
1767int15_handler32_ret:
1768endif
1769 pop es
1770 pop ds
1771 popf
1772 jmp iret_modify_cf
1773
1774apm_call:
1775 call _apm_function
1776 jmp int15_handler_popa_ret
1777
1778int15_handler_mouse:
1779 call _int15_function_mouse
1780 jmp int15_handler_popa_ret
1781
1782if VBOX_BIOS_CPU ge 80386
1783int15_handler32:
1784 ;; need to save/restore 32-bit registers
1785 .386
1786 pushad
1787 call _int15_function32
1788 popad
1789 .286
1790 jmp int15_handler32_ret
1791endif
1792
1793;;
1794;; Perform an IRET but retain the current carry flag value
1795;;
1796iret_modify_cf:
1797 jc carry_set
1798 push bp
1799 mov bp, sp
1800 and byte ptr [bp + 6], 0FEh
1801 or word ptr [bp + 6], 0200h
1802 pop bp
1803 iret
1804carry_set:
1805 push bp
1806 mov bp, sp
1807 or word ptr [bp + 6], 0201h
1808 pop bp
1809 iret
1810
1811;;
1812;; INT 74h handler - PS/2 mouse (IRQ 12)
1813;;
1814int74_handler proc
1815
1816 sti
1817 DO_pusha
1818 push es
1819 push ds
1820 xor ax, ax
1821 push ax ; placeholder for status
1822 push ax ; placeholder for X
1823 push ax ; placeholder for Y
1824 push ax ; placeholder for Z
1825 push ax ; placeholder for make_far_call bool
1826 C_SETUP
1827 call _int74_function
1828 pop cx ; pop make_far_call flag
1829 jcxz int74_done
1830
1831 ;; make far call to EBDA:0022
1832if VBOX_BIOS_CPU ge 80186
1833 push 0
1834else
1835 xor ax, ax
1836 push ax
1837endif
1838 pop ds
1839 push ds:[40Eh]
1840 pop ds
1841 call far ptr ds:[22h]
1842int74_done:
1843 cli
1844 call eoi_both_pics
1845 add sp, 8 ; remove status, X, Y, Z
1846 pop ds
1847 pop es
1848 DO_popa
1849 iret
1850
1851int74_handler endp
1852
1853int76_handler proc
1854
1855 ;; record completion in BIOS task complete flag
1856 push ax
1857 push ds
1858 mov ax, 40h
1859 mov ds, ax
1860 mov byte ptr ds:[8Eh], 0FFh
1861 call eoi_both_pics
1862 pop ds
1863 pop ax
1864 iret
1865
1866int76_handler endp
1867
1868
1869;;
1870;; IRQ 8 handler (RTC)
1871;;
1872int70_handler:
1873 push es
1874 push ds
1875 DO_pusha
1876 C_SETUP
1877 call _int70_function
1878 DO_popa
1879 pop ds
1880 pop es
1881 iret
1882
1883
1884
1885if VBOX_BIOS_CPU lt 80386
1886;
1887; We're tight on space down below in the int08_handler, so put
1888; the 16-bit rollover code here.
1889;
1890int08_maybe_rollover:
1891 ja int08_rollover
1892 cmp ax, 00B0h
1893 jb int08_rollover_store
1894 ;; there has been a midnight rollover
1895int08_rollover:
1896 xor dx, dx
1897 xor ax, ax
1898
1899 inc byte ptr ds:[70h] ; increment rollover flag
1900int08_rollover_store:
1901 jmp int08_store_ticks
1902endif
1903
1904
1905;; --------------------------------------------------------
1906;; 8x8 font (first 128 characters)
1907;; --------------------------------------------------------
1908 BIOSORG 0FA6Eh, 0FA6Ch
1909include font8x8.inc
1910
1911
1912;; --------------------------------------------------------
1913;; INT 1Ah handler - Time of the day + PCI BIOS
1914;; --------------------------------------------------------
1915 BIOSORG_CHECK 0FE6Eh ; fixed wrt preceding table
1916int1a_handler:
1917if VBOX_BIOS_CPU ge 80386
1918 cmp ah, 0B1h
1919 jne int1a_normal
1920
1921 push es
1922 push ds
1923 C_SETUP
1924 .386
1925 pushad
1926 call _pci16_function
1927 popad
1928 .286
1929 pop ds
1930 pop es
1931 iret
1932endif
1933
1934int1a_normal:
1935 push es
1936 push ds
1937 DO_pusha
1938 C_SETUP
1939int1a_callfunction:
1940 call _int1a_function
1941 DO_popa
1942 pop ds
1943 pop es
1944 iret
1945
1946
1947;; --------------------------------------------------------
1948;; Timer tick - IRQ 0 handler
1949;; --------------------------------------------------------
1950 BIOSORG 0FEA5h, 0FEA3h
1951int08_handler:
1952if VBOX_BIOS_CPU ge 80386
1953 .386
1954 sti
1955 push eax
1956else
1957 sti
1958 push ax
1959endif
1960 push ds
1961 push dx
1962 mov ax, 40h
1963 mov ds, ax
1964
1965if VBOX_BIOS_CPU ge 80386
1966 mov eax, ds:[6Ch] ; get ticks dword
1967 inc eax
1968else
1969 mov ax, ds:[6Ch] ; get ticks dword
1970 mov dx, ds:[6Ch+2]
1971 inc ax ; inc+jz+inc saves two bytes over add+adc.
1972 jnz int08_compare
1973 inc dx
1974int08_compare:
1975endif
1976
1977 ;; compare eax to one day's worth of ticks (at 18.2 Hz)
1978if VBOX_BIOS_CPU ge 80386
1979 cmp eax, 1800B0h
1980 jb int08_store_ticks
1981else
1982 cmp dx, 18h
1983 jb int08_store_ticks
1984 jmp int08_maybe_rollover
1985endif
1986
1987if VBOX_BIOS_CPU ge 80386
1988 ;; there has been a midnight rollover
1989 xor eax, eax
1990 inc byte ptr ds:[70h] ; increment rollover flag
1991
1992int08_store_ticks:
1993 mov ds:[6Ch], eax
1994else
1995int08_store_ticks:
1996 mov ds:[6Ch], ax
1997 mov ds:[6Ch+2], dx
1998endif
1999
2000 ;; time to turn off floppy drive motor(s)?
2001 mov al, ds:[40h]
2002 or al, al
2003 jz int08_floppy_off
2004 dec al
2005 mov ds:[40h], al
2006 jnz int08_floppy_off
2007 ;; turn motor(s) off
2008 mov dx, 03F2h
2009 in al, dx
2010 and al, 0CFh
2011 out dx, al
2012int08_floppy_off:
2013
2014 int 1Ch ; call the user timer handler
2015
2016 cli
2017 call eoi_master_pic
2018 pop dx
2019 pop ds
2020if VBOX_BIOS_CPU ge 80386
2021 pop eax
2022 .286
2023else
2024 pop ax
2025endif
2026 iret
2027
2028
2029;; --------------------------------------------------------
2030;; Initial interrupt vector offsets for POST
2031;; --------------------------------------------------------
2032 BIOSORG 0FEF3h, 0FEF1h
2033vector_table:
2034
2035
2036
2037;; --------------------------------------------------------
2038;; BIOS copyright string
2039;; --------------------------------------------------------
2040 BIOSORG 0FF00h, 0FEFEh
2041bios_string:
2042 db BIOS_COPYRIGHT
2043
2044
2045;; --------------------------------------------------------
2046;; IRET - default interrupt handler
2047;; --------------------------------------------------------
2048 BIOSORG 0FF53h, 0FF51h
2049
2050dummy_iret:
2051 iret
2052
2053
2054;; --------------------------------------------------------
2055;; INT 05h - Print Screen service
2056;; --------------------------------------------------------
2057 BIOSORG_CHECK 0FF54h ; fixed wrt preceding
2058int05_handler:
2059 ;; Not implemented
2060 iret
2061
2062include smidmi.inc
2063
2064;; --------------------------------------------------------
2065;; Processor reset entry point
2066;; --------------------------------------------------------
2067 BIOSORG 0FFF0h, 0FFEEh
2068cpu_reset:
2069 ;; This is where the CPU starts executing after a reset
2070 jmp far ptr post
2071
2072 ;; BIOS build date
2073 db BIOS_BUILD_DATE
2074 db 0 ; padding
2075 ;; System model ID
2076 db SYS_MODEL_ID
2077 ;; Checksum byte
2078 db 0FFh
2079
2080
2081BIOSSEG ends
2082
2083 end
2084
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