VirtualBox

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

Last change on this file since 85639 was 84901, checked in by vboxsync, 4 years ago

BIOS: Do not hardcode conventional memory size, query from CMOS instead.

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