VirtualBox

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

Last change on this file since 67104 was 67065, checked in by vboxsync, 8 years ago

Whitespace.

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