University of Maryland MISSL

LinuxBIOS:
A Study of BIOS Services as used by Microsoft Windows XP.

by
Adam Sulmicki ( adam@cfar.umd.edu)
http://www.eax.com
at
The Maryland Information Systems Security Lab
(MISSL)


Abstract

This paper describes an extensive analysis of the BIOS Services. The BIOS Services in question are: (a) "BIOS Interrupts", (b) BIOS32 Services, (c) Plug and Play BIOS Services, (d) BIOS Data Area and Extended BIOS Data Area, (e) Advanced Configuration and Power Interface (ACPI). In the above "BIOS Interrupts" means the subset of interrupts that are implemented by the BIOS. This study has been done to find out which of the BIOS Services are used by Microsoft's operating system. Advanced analysis has been performed on each BIOS Service's usage by said operating system. The operating systems analyzed are Windows 2000 and Windows XP.


Table of Contents


1. Introduction

This paper describes an extensive analysis of the BIOS Services. The BIOS Services in question are: (a) "BIOS Interrupts", (b) BIOS32 Services, (c) Plug and Play BIOS Services, (d) BIOS Data Area and Extended BIOS Data Area, (e) Advanced Configuration and Power Interface (ACPI). In the above "BIOS Interrupts" means the subset of interrupts that are implemented by the BIOS. This study has been done to find out which of the BIOS Services are used by Microsoft's operating system. Advanced analysis has been performed on each BIOS Service's usage by said operating system. The operating systems analyzed are Windows 2000 and Windows XP.

As we will find out, Interrupt-based BIOS Services make up the core part of the communication between BIOS and Windows. Consequently, they make up the bulk of the paper. This paper describes an extensive analysis of a subset of the interrupts. When we study interrupts, the interrupts we are interested most in are the ones that are implemented by the BIOS. The study of the BIOS interrupts analyze how each BIOS Interrupt is used by Windows 2000 and Windows XP. Advanced analysis has been performed on each interrupt's usage by said operating systems.

Said work will help us facilitate running Windows OS on top of LinuxBIOS [18] . It is also relevant for our work on SEBOS [20] [33] . At the present time, the idea is to implement an extra stage module, which would be loaded by LinuxBIOS. This module would add support for some subset of "classic" PC-style BIOS Services. Said module in turn would load the next stage which in our case would be Microsoft Windows.

This paper is a superset of my earlier paper titled: " LinuxBIOS: A Study of BIOS Interrupts as used by Microsoft Windows 2000" [32] .

This paper is a subset of my forthcoming paper titled: " LinuxBIOS: How LinuxBIOS boots Windows" [XX] .

Most of the work was done by me, Adam Sulmicki (adam[at]cfar.umd.edu) , with help from Adam Agnew (agnew[at]cs.umd.edu). Lots of thanks go to William A. Arbaugh (waa[at]cs.umd.edu) who made all this work possible. Finally, for list of other people who contributed to the paper, please, see Acknowledgments section.


2. System Overview

Before we go into details on BIOS Services, first let's go briefly over our setup.


2.1. Hardware

Some more details about our hardware setup.

The system consisted of:

It all was set up on a local LAN, where In-Target Probe , Host, Target and Laptop all shared the same subnet.
setup left side set front view setup - right side

In our Target System I disabled everything in BIOS that was unnecessary. It turned out to be quite a bit, given the numerous things built into the SIS630 chipset. The end result was that these things were disabled:

NOTE: The below interrupt list (in Section 3.1.2. BIOS Interrupts Overview), which lists how many times each interrupt is called, was done with everything enabled in BIOS. It was also done using a different BIOS, thus the number of calls will be different than what is in the detailed analysis below.


2.2. BIOS

The motherboard normally comes with Award/Phoenix BIOS [35] [36] (the two companies have merged). First I used release 05/08/2001, later I upgraded to 05/02/2001. However, during the debugging process, the system developed some unexplained problems, possibly a hardware failure. Since I discovered that switching to AMI BIOS [34] cures the problems, I stuck with AMI BIOS and the same motherboard for the duration of the experiment in order to preserve all addressing used in the study. The BIOS I ended up using:

BIOS:
	AMIBIOS 03/08/01
	
	686
	AMIBIOS
	(c) 1999
	AR75
	1666


2.3. LILO

The next issue was where to start our debugging. In our system BIOS would load LILO, which in turn would boot up either Microsoft Windows 2000/XP or Red Hat Linux 7.1. Studying LILO sources and docs, it seems that it will load the client into the area starting at 0x7C00 then make a jump to this address to start the client.

The LILO as shipped with RedHat 7.1 is lilo-21.4.4-13 which can be found here [13] . Of particular interest will be this Technical Overview [12] which gives a brief description on how LILO jump-starts the client, pages 1-2. To quote:

address where LILO loads "OS" and passes control


The chain loader moves [..] the boot sector to 0x7C00. 
After that it passes control to the boot sector.

That is pretty good, but the source is where the ultimate proof lies :-) Hopefully the code below is self explanatory (On a curious note, older versions of the code would just use a far jump in the form "jmpi #BOOTSEG*16,0"). Thus:

bootsect.S:33
	BOOTSEG   = 0x07C0	! original address of boot-sector


chain.S:143-169
        xor     ax,ax		! clear AX register
        mov     bx,#BOOTSEG*16                                 
        push    ax
        push    bx
        retf
Another issue that came to my attention is that LILO is using interrupts for its own needs so we need to be careful not to pollute our results with interrupts from LILO. The three interrupts that came to our attention were:

Address 0x7C00 is used in several places (two: a) start of LILO, and b) start client) before the final passing of control to the client. In the end the way I decided to pin-point the start of the client (Microsoft Windows) was as follows:

I would let the Target computer start normally, and wait until the LILO command prompt came up. Then, using the Host system, I would put the Target system into Stopped Mode (Alt-F5), activate a breakpoint at 0x7C00, and let it Continue (F5). Then I would wait for the Target system to reach the instruction at 0x7C00, at which point the debugger's "Execute"-style breakpoint would be triggered. Once it hit this breakpoint I would start from that point on to record activity of whichever interrupt I was working on.

Another way to start debugging:

It is based on fact that 0x7C00 is used only TWICE. First time during starting LILO, and second time during starting Windows.

DONE. Target should be stopped just at the time it is about to pass control to Windows.

2.4. Operating System

Our study focuses on "Windows" series of "operating systems" from Microsoft Corporation [30] . The two versions of the said operating system we have analyzed in this study are:

In both cases it just just "standard" installation, with no extra programs/drivers installed.


2.5. Shadow BIOS

During the debugging process it was sometimes necessary to modify one or more of the following items for certain interrupts: a) the vector table, b) Windows code, c) BIOS code. This was necessary in order to see what was going on when some routine was used an excessive number of times, clouding our view of the other parts of the code.

Points a and b were pretty easy to deal with, but c was more difficult. We considered a number of different solutions:

Of all the three method mentioned above, the third one (c) is the best. The whole description of the third (c) method basically boils down to the executing the two simple commands as shown below:


dport 0CF8h = 80000070h
wport 0CFEh = 1000h

This is the syntax as used with the Source Point debugger, and is for the SIS630 chipset.

The relevant references here are PCI Hardware and Software Architecture and Design [4], and WinDB user's Guide by American Arium [5].


2.6. Notes on Debugging


3. BIOS Services

This layout has been heavily influenced by Phoenix's Manual description of BIOS Services [7]. Since I probably couldn't come up with anything better I decided to follow it as well. However, it is expanded by ACPI Chapter which is not present in the said manual.


3.1. BIOS Interrupts

We do an extensive analysis of a subset of interrupts. The interrupts we are interested in are the ones that are implemented by BIOS. We attempt find out which of the BIOS interrupts are used by Microsoft's operating system. We do advanced analysis on each interrupt's usage by said operating system. We do analysis of both Windows 2000 (red tables below), and Windows XP (orange fields below).


3.1.1. Defining BIOS Interrupts

The first question was "Which interrupts are of interest to us?". That is, "Which interrupts are serviced by BIOS?". As a reference I have used "PhoenixBIOS 4.0, Revision 6, User's Manual" from Phoenix Technologies Ltd. [7], available from Phoenix's Web site ( local copy ). There is also "Ralf Brown's Interrupt List" [6] which is available from here and here and here which I have used as an auxiliary reference when something was not documented in Phoenix's manual. Overall Phoenix's manual is a pretty good resource which documents BIOS and BIOS-supported interrupts, and lists the function of each interrupt with a short description.

On page 80 of Phoenix's BIOS manual there is this list:

ADDR	  	INT	Description 				Status 
  0		00 	Divide by zero 				Not Supported 
  4		01 	Single step 				Not Supported 
  8		02 	Non-Maskable interrupt 			Supported 
  C		03 	Breakpoint 				Not Supported 
 10		04 	Overflow 				Not Supported 
 14		05 	Print Screen Interrupt 			Supported 
 18		06 	286 LoadAll Handler 			Supported 
 1C		07 	Reserved 				Not Supported 
 20		08 	IRQ0 - System Timer Interrupt 		Supported 
 24		09 	IRQ1 - Keyboard Interrupt 		Supported 
 28		0A 	IRQ2 - Reserved 			Not Supported 
 2C		0B 	IRQ3 - COM2: Interrupt 			Supported 
 30		0C 	IRQ4 - COM1: Interrupt 			Supported 
 34		0D 	IRQ5 - LPT2: Interrupt 			Supported 
 38		0E 	IRQ6 - Floppy Disk Interrupt 		Supported 
 3C		0F 	IRQ7 - LPT1: Interrupt 			Supported 
 40		10 	BIOS Video Interface 			Supported 
 44		11 	BIOS Equipment Check 			Supported 
 48		12 	BIOS Memory Request 			Supported 
 4C		13 	BIOS Fixed Disk/Diskette Interface 	Supported 
 50		14 	BIOS Serial Interface 			Supported 
 54		15 	BIOS System Functions Interface 	Supported 
 58		16 	BIOS Keyboard Interface 		Supported 
 5C		17 	BIOS Parallel Printer Interface 	Supported 
 60		18 	BIOS Secondary Boot Request 		Supported 
 64		19 	BIOS Primary Boot Request 		Supported 
 68		1A 	BIOS System Timer Interface 		Supported 
 6C		1B 	BIOS Control Break Interrupt 		Supported 
 70		1C 	BIOS User System Timer Interrupt 	Supported 
 74		1D 	BIOS Video Init Parameters 		Supported 
 78		1E 	BIOS Diskette Parameters 		Supported 
 7C		1F 	BIOS Video Graphic Characters 		Supported 


100		40 	BIOS Diskette (when fixed disk present) Supported 
104		41 	BIOS Fixed disk 0 parameters 		Supported 


118		46 	BIOS Fixed disk 1 parameters 		Supported 
1C0		70 	IRQ8 - Real time clock interrupt 	Supported 
1C4		71 	IRQ9 - IRQ2 redirection 		Supported 
1C8		72 	IRQ10 - Reserved 			Not Supported 
1CC		73 	IRQ11 - Reserved 			Not Supported 
1D0		74 	IRQ12 - Available/PS/2 Mouse 		Supported 
1D4		75 	IRQ13 - Math coprocessor 		Supported 
1D8		76 	IRQ14 - Primary IDE HDD 		Supported 
1DC		77 	IRQ15 - Available/Secondary IDE HDD 	Supported

In the above list all interrupts with the word "BIOS" in the Description field were considered as implemented and supported by BIOS. The entries in the blue box above were the subject of further study.

The ADDR field was calculated by multiplying each interrupt by 4.


3.1.2. BIOS Interrupts Overview

For the next step we set up the ECM-20 In-Target Probe by American Arium [37] [38] . Using two computers ('Host' and 'Target'), each interrupt was analyzed to determine how many times it was being called while Microsoft Windows was starting up. The results were as follows (shown in the "NT" column):

ADDR	NT	INT	Description 				Status 
  0		00 	Divide by zero 				Not Supported 
  4		01 	Single step 				Not Supported 
  8		02 	Non-Maskable interrupt 			Supported 
  C		03 	Breakpoint 				Not Supported 
 10		04 	Overflow 				Not Supported 
 14		05 	Print Screen Interrupt 			Supported 
 18		06 	286 LoadAll Handler 			Supported 
 1C		07 	Reserved 				Not Supported 
 20		08 	IRQ0 - System Timer Interrupt 		Supported 
 24		09 	IRQ1 - Keyboard Interrupt 		Supported 
 28		0A 	IRQ2 - Reserved 			Not Supported 
 2C		0B 	IRQ3 - COM2: Interrupt 			Supported 
 30		0C 	IRQ4 - COM1: Interrupt 			Supported 
 34		0D 	IRQ5 - LPT2: Interrupt 			Supported 
 38		0E 	IRQ6 - Floppy Disk Interrupt 		Supported 
 3C		0F 	IRQ7 - LPT1: Interrupt 			Supported 
 40	~4	10 	BIOS Video Interface 			Supported 
 44	 2	11 	BIOS Equipment Check 			Supported 
 48	 1	12 	BIOS Memory Request 			Supported 
 4C	lots	13 	BIOS Fixed Disk/Diskette Interface 	Supported 
 50	 1	14 	BIOS Serial Interface 			Supported 
 54	lots	15 	BIOS System Functions Interface 	Supported 
 58	~40	16 	BIOS Keyboard Interface 		Supported 
 5C	 3	17 	BIOS Parallel Printer Interface 	Supported 
 60	 1	18 	BIOS Secondary Boot Request 		Supported 
 64	 1	19 	BIOS Primary Boot Request 		Supported 
 68	~14	1A 	BIOS System Timer Interface 		Supported 
 6C	 1	1B 	BIOS Control Break Interrupt 		Supported 
 70	lots+	1C 	BIOS User System Timer Interrupt 	Supported 
 74	 1	1D 	BIOS Video Init Parameters 		Supported 
 78	 2+	1E 	BIOS Diskette Parameters 		Supported 
 7C	 8	1F 	BIOS Video Graphic Characters 		Supported 


100	 6	40 	BIOS Diskette (when fixed disk present) Supported 
104	 1	41 	BIOS Fixed disk 0 parameters 		Supported 


118	 1	46 	BIOS Fixed disk 1 parameters 		Supported 

1C0		70 	IRQ8 - Real time clock interrupt 	Supported 
1C4		71 	IRQ9 - IRQ2 redirection 		Supported 
1C8		72 	IRQ10 - Reserved 			Not Supported 
1CC		73 	IRQ11 - Reserved 			Not Supported 
1D0		74 	IRQ12 - Available/PS/2 Mouse 		Supported 
1D4		75 	IRQ13 - Math coprocessor 		Supported 
1D8		76 	IRQ14 - Primary IDE HDD 		Supported 
1DC		77 	IRQ15 - Available/Secondary IDE HDD 	Supported

Where:
"~" means approximate number of interrupt calls,
"N+" means more than N interrupt calls,
"lots" means a large number of interrupt calls.


3.1.3. The BIOS Interrupt Map

This was pretty good, but it still did not give us the details we wanted. I had set access-breakpoints for each vector in the vector table, so it was not clear if the vector in the vector table was just being read off or if it was an actual vector call. By the same token it was not clear if the interrupt was used by Windows or if it was used internally by the BIOS. Thus, I did the work again, this time analyzing each interrupt call in detail to see exactly what was happening.

The Gory Details

Below is a detailed description of what happens to each BIOS interrupt from (a) when LILO passes control to Windows until (b) Windows sets up its own interrupt vector table elsewhere in memory. It will set up its own interrupt vector table by means of switching to protected mode and then using LIDT and SIDT instructions.

10 BIOS Video Interface

ADDR	NT	INT	Description 				Status 
 40	13/11	10      BIOS Video Interface 			Supported 
VECTOR TABLE:
		0000:0040 C000:07CB 
BIOS (AMI):
	start	C000:07CB FB               STI         
	end	C000:07F5 CF               IRET     
WINDOWS 2000:			
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
	2000:000002E4 CD10             INT         10
		one, 
		AH=12 - BIOS Window Extension v1.1 - GET BLANKING ATTRIBUTE
		AL=02
		BX=0301
		two,
		AH=00 - Set Video Mode
		AL=03 - = T  80x25  9x16  720x400   16   8   B800  VGA
[screen cleared up, cursor at left-top corner]
		three, 
		AH=20, ?????
		AL=00
			what the heck is that. 
			some very simple function.
			it must be for some other systems. 
			it is not implemented on my system. 
			the function just falls through.
		four
		AH=0A - VIDEO - WRITE CHARACTER ONLY AT CURSOR POSITION
		AL=20 - space
		SEE NOTE4
	2000:00000980 CD10             INT         10
		AH=02 - VIDEO - SET CURSOR POSITION
		DH=7F = row 127,   bottom-most row
		DL=00 = column 00 ,left-most   column
			hide cursor
[cursor disappears from screen, all blank screen]	
	1000:00004EF1 268B0F           MOV         CX,word ptr ES:[BX]
		reads INT 10 vector table entry (7CB) into CX
	1000:00001C88 CD10             INT         10
		one
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=02 - 02h ROM 8x14 character font pointer
		two
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=03 -  03h ROM 8x8 double dot font pointer
		three
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=04 - 04h ROM 8x8 double dot font (high 128 characters)
		four
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=05 - 05h ROM alpha alternate (9 by 14) pointer (EGA,VGA)
		five
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=06 - 06h ROM 8x16 font (MCGA, VGA)
		six
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=07 - 07h ROM alternate 9x16 font (VGA only) 
[still text mode]
[text banner "Starting Windows"]
[the bar below ALL white.]
[protected mode]
	0008:80063C31 8B048D00000000 MOV EAX,dword ptr [00000000][ECX*4]
		reads INT 10 vector table entry (7CB) into EAX
		ECX=10
[screen all blank again]
[Virtual86 mode]
	2000:000001C8 CD10             INT         10
		AH=00 - VIDEO - SET VIDEO MODE
		AL=12 - 12h = G  80x30  8x16  640x480  16/256K.A000 VGA,ATI VIP
			Virtual86 mode!
			I have caught this interrupt via EXIT routine!
			it must be using alternate vector table!
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+40h (ESI+40)
[screen is blank again]
	1000:00000000 CD10             INT         10
		AH=00 - VIDEO - SET VIDEO MODE
		AL=12 - 12h = G 80x30  8x16  640x480 16/256K . A000 VGA,ATI VIP
[windows fully running, with "Start" button]
[no more interrupt 10h]
WINDOWS XP:			
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
	2000:000002E4 CD10             INT         10
		one, 
		AH=12 - BIOS Window Extension v1.1 - GET BLANKING ATTRIBUTE
		AL=02
		BX=0301
		two,
		AH=00 - Set Video Mode
		AL=03 - = T  80x25  9x16  720x400   16   8   B800  VGA
[screen cleared up, cursor at left-top corner]
		three, 
		AH=20, ?????
		AL=00
			what the heck is that. 
			some very simple function.
			it must be for some other systems. 
			it is not implemented on my system. 
			the function just falls through.
		four
		AH=0A - VIDEO - WRITE CHARACTER ONLY AT CURSOR POSITION
		AL=20 - space
		SEE NOTE4
	2000:00000970 CD10        INT         10
		AH=02 - VIDEO - SET CURSOR POSITION
		DH=7F = row 127,   bottom-most row
		DL=00 = column 00 ,left-most   column
			hide cursor
[cursor disappears from screen, all blank screen]	
	1000:6A1C 268B07 MOV DX,word ptr ES:[BX]
		reads INT 10 vector table entry (7CB) into DX
	1000:2828 CD10        INT         10
		one
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=02 - 02h ROM 8x14 character font pointer
		two
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=03 -  03h ROM 8x8 double dot font pointer
		three
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=04 - 04h ROM 8x8 double dot font (high 128 characters)
		four
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=05 - 05h ROM alpha alternate (9 by 14) pointer (EGA,VGA)
		five
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=06 - 06h ROM 8x16 font (MCGA, VGA)
		six
		AX=1130 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
		BH=07 - 07h ROM alternate 9x16 font (VGA only) 
[windows fully running, with "Start" button]
[no more interrupt 10h]
NOTE0:
	windows shutting down:

	[blank screen]
		1000:00000000 CD10             INT         10
			AH=00 - VIDEO - SET VIDEO MODE
			AL=03 - = T  80x25  9x16  720x400   16  8  B800 VGA
	[blank screen w/ cursor at left-top corner]
		2000:00001C88 CD10             INT         10
			AH=00 - VIDEO - SET VIDEO MODE
			AL=12
	[all blank  screen]
	[a bit of delay]
	["it is now safe to turn off computer"]
NOTE1:
	video BIOS 

	This is Actually VIDEO BIOS, not "MAIN" BIOS.
	The Interrupt code is located at segment C000 which is video BIOS. 
NOTE2:
	LILO does use interrupt 10 as well

	0B00:000008EC CD10             INT         10  // write "\r"
	[and so on until text below shows]
	"LILO boot:\r\nLoading winblows\r\n"
NOTE3:
	"map" of int 10.

	it is for Award/Phoenix BIOS
	and NOT for AMI BIOS on which most stuff is done.

	this shows how int 10/vector table for 10 
	is used/setup inside of the BIOS.
	BIOS:
	F000:0000E919 AA               STOS        byte ptr [DI]
		40hP = C0000712 
		40hP = C0001212 
		instruction called twice
	F000:0000C100 67F366AB         REP STOS    dword ptr [EDI]
		40hP	5AA5A55A 

	F000:0000E2CD : zero vector table
	F000:0000E2E1 : test zeroing VT was successful
	F000:00001B1B : set all interrupts to F000:E816
	F000:00001B35 : set kbd interrupt  to F000:F065
	F000:00001B35 : set kbd interrupt  to F000:FF53
	F000:00002A6A : load all vector table into single reg ?????
			1st BIOS screen shows up
	F000:0000BC58 : some memory comparison/verification 
				repeats 4 times total

NOTE4:
	weird code: 
		-lots of interrupt calls grouped together.
		 grouped interrupts are : interrupts 10-19
	-int 10 is called repeatedly from here with varying arguments
NOTE5:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- small differences of offset in a segment.
		- does not save vector table anymore.

	minor differences:
		- use different registers for return value.
		- does not do one vector table read anymore.

	major differences:
		- does not do two interrupt calls anymore.
		- 4 less "calls" at end.

11 BIOS Equipment Check

ADDR	NT	INT	Description 				Status 
 44	1/1	11 	BIOS Equipment Check 			Supported 
VECTOR TABLE:
		0000:0044 F000:F84D
BIOS (AMI):
	start	F000:F84D E855B2           CALL  near16 ptr 0000aaa5
	end	F000:F858 CF               IRET 
WINDOWS 2000:
[blank screen]
	1000:00002A8C CD11             INT         11
		return:
			AX = 22h = 100010b (FPU, 80x25 CGA)
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5  REP MOVS    dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+44h (ESI+44)
[windows fully running, with "Start" button]
[no more interrupt 11h]
WINDOWS XP:
[blank screen]
	1000:0000403C CD11       INT         11
		return:
			AX = 22h = 100010b (FPU, 80x25 CGA)
[windows fully running, with "Start" button]
[no more interrupt 11h]
NOTE0:
	windows shutdown
	[reboot]
NOTE1:
	in the above the int 11 was called so that
	later windows could check for mouse.

	test for mouse (4h-> 100b)

	1000:00002A8C CD11             INT         11
	1000:00002A8E A90400           TEST        AX,0004
NOTE2:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- small differences of offset in a segment.
		- does not save vector table anymore.

12 BIOS Memory Request

ADDR	NT	INT	Description 				Status 
 48	0/0	12 	BIOS Memory Request 			Supported 
VECTOR TABLE:
		0000:0048 F000:F841
BIOS (AMI):
	start	F000:F841 FB               STI  
	end	F000:F84A CF               IRET   
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5   REP MOVS    dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+48h (ESI+48)
[windows fully running, with "Start" button]
[no more interrupt 12h]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 12h]
NOTE0:
	windows shutdown
	[reboot]
NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

13 BIOS Fixed Disk/Diskette Interface

ADDR	NT	INT	Description 				Status 
 4C	lots	13 	BIOS Fixed Disk/Diskette Interface 	Supported 
VECTOR TABLE:
		0000:004C F000:EED2
BIOS (AMI):
	start	F000:EED2 E961FF           JMP near16 ptr 0000ee36
	end	F144:03E4 CF               IRET        
	end2	F144:03F1 CA0200	   RETF 0002
WINDOWS 2000:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
	0000:00007C70 CD13             INT         13
		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			CX = FEFF, max 255 sectors, max 254 cylinders
			DX = FE01, max 254 heads,   1 drive
	0000:00007D07 CD13             INT         13
		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
		BX = 55AAh, The Magic Number 
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			BX = AA55h, extension installed
			AH = 21, 2.1 / EDD-1.1
			CX = 5 = 101(b), 
				extended disk *access* functions SUPPORTED
				*removable* functions NOT supported
				*EDD* functions SUPPORTED
		SEE NOTE0
[
#	0000:00007D26 CD13             INT         13
#		AH = 42, IBM/MS INT 13 Extensions - EXTENDED READ
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			DS:SI = 0000:7BC2
#				10 - size of packet
#				00 - reserved
#				0001 - number of blocks read
#		one, two, three ... LOTS .. 
#SEE *IMPORTANT* NOTE1
]

[
#	2000:0000061F CD13             INT         13
#		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			CX = FEFF, max 255 sectors, max 254 cylinders
#			DX = FE01, max 254 heads,   1 drive
#	2000:00000FE1 CD13             INT         13
#		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
#		BX = 55AAh, The Magic Number 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			BX = AA55h, extension installed
#			AH = 21, 2.1 / EDD-1.1
#			CX = 5 = 101(b), 
#				extended disk *access* functions SUPPORTED
#				*removable* functions NOT supported
#				*EDD* functions SUPPORTED
#		SEE NOTE0
#	2000:00001010 CD13             INT         13
#		AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		result
#		      DS:SI = 609C:000C
#		      609C:000C 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
#		      609C:001C 80 A7 54 02 00 00 00 00 00 02 00 00 00 00 00 00
#	2000:0000061F CD13             INT         13
#		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
#		AL = 1,  number of sectors to read (must be nonzero)
#		CH = 00, low eight bits of cylinder number
#		CL = 01, sector number 1-63 (bits 0-5)
#			high two bits of cylinder (bits 6-7, hard disk only) 
#		DH = 00 head number
#		DL = 80, drive number (bit 7 set for hard disk)
#	2000:000006F3 CD13             INT         13
#		AH = 42, IBM/MS INT 13 Extensions - EXTENDED READ
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			DS:SI = 0000:0C0F
#				10 - size of packet
#				00 - reserved
#				0001 - number of blocks read
#SEE *IMPORTANT* NOTE2
]
	1000:00003F72 CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return
			AH=03h , fixed disk
			CX:DX = 00FA:0C53F, number of 512b blocks
	1000:00003F83 CD13             INT         13
		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			CX = FEFF, max 255 sectors, max 254 cylinders
			DX = FE01, max 254 heads,   1 drive
	1000:00003F72 CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DL=81h ,10000000(b) -> bit 7 on -> hard disk, ?????
		return
			AH=00h , no such drive.
		SEE NOTE3
	1000:00003989 CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DH=00, floppy only?????
		return
			AH=00, no such drive.
	1000:00003E18 CD13             INT         13
		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
		AL = 1,  number of sectors to read (must be nonzero)
		CH = 00, low eight bits of cylinder number
		CL = 01, sector number 1-63 (bits 0-5)
			high two bits of cylinder (bits 6-7, hard disk only) 
		DH = 00 head number
		DL = 80, drive number (bit 7 set for hard disk)
	1000:00003FE5 CD13             INT         13
		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
		BX = 55AAh, The Magic Number 
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			BX = AA55h, extension installed
			AH = 21, 2.1 / EDD-1.1
			CX = 5 = 101(b), 
				extended disk *access* functions SUPPORTED
				*removable* functions NOT supported
				*EDD* functions SUPPORTED
		SEE NOTE0
	1000:00004013 CD13             INT         13
		AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS 
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		result
			DS:SI = 16F3:0D0A
		16F3:00000D0A 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
		16F3:00000D1A 80 A7 54 02 00 00 00 00 00 02 28 00 00 00 80 00 
[
#
#	2000:0000061F CD13             INT         13
#		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			CX = FEFF, max 255 sectors, max 254 cylinders
#			DX = FE01, max 254 heads,   1 drive
#	2000:00000FE1 CD13             INT         13
#		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
#		BX = 55AAh, The Magic Number 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			BX = AA55h, extension installed
#			AH = 21, 2.1 / EDD-1.1
#			CX = 5 = 101(b), 
#				extended disk *access* functions SUPPORTED
#				*removable* functions NOT supported
#				*EDD* functions SUPPORTED
#		SEE NOTE0
#	2000:00001010 CD13             INT         13
#		AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		result
#		      DS:SI = 609C:000C
#		      609C:000C 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
#		      609C:001C 80 A7 54 02 00 00 00 00 00 02 00 00 00 00 00 00
#	2000:0000061F CD13             INT         13
#		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
#		AL = 1,  number of sectors to read (must be nonzero)
#		CH = 00, low eight bits of cylinder number
#		CL = 01, sector number 1-63 (bits 0-5)
#			high two bits of cylinder (bits 6-7, hard disk only) 
#		DH = 00 head number
#		DL = 80, drive number (bit 7 set for hard disk)
#	2000:000006F3 CD13             INT         13
#		AH = 42, IBM/MS INT 13 Extensions - EXTENDED READ
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			DS:SI = 0000:0C0F
#				10 - size of packet
#				00 - reserved
#				0001 - number of blocks read
#SEE *IMPORTANT* NOTE2
]
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5   REP MOVS    dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+4Ch (ESI+4C)
[windows fully running, with "Start" button]
[no more interrupt 13h]
WINDOWS XP:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
	0000:00007C81 CD13        INT         13
		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286, ONV,PS,ESDI,SCSI)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			CX = FEFF, max 255 sectors, max 254 cylinders
			DX = FE01, max 254 heads,   1 drive
	0000:00007D42 CD13             INT         13
		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
		AL = 1,  number of sectors to read (must be nonzero)
		CH = 67, low eight bits of cylinder number
		CL = 81, sector number 1-63 (bits 0-5)
			high two bits of cylinder (bits 6-7, hard disk only) 
		DH = 00 head number
		DL = 80, drive number (bit 7 set for hard disk)

		one,two,three,four,five,six,seven
		executes around 16 (10h) times

		It is an loop, which counter stored in DS:000E (07C0:000E).

			start of function 0000:00007CC7 
	
			start of loop:	  0000:00007CCB

			interrupt:	  0000:00007D42   INT 13

			end   of loop:    0000:00007D58 : JNE
			next line 	  0000:00007D5C

		NOTE1XP: make NOTE out of this.

	0D00:00000081 CD13             INT         13
		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			CX = FEFF, max 255 sectors, max 254 cylinders
			DX = FE01, max 254 heads,   1 drive
[
#	0D00:0000142 CD13             INT         13
#		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
#		AL = 01, number of sectors to read (must be nonzero)
#		CH = E9, low eight bits of cylinder number
#		CL = 89, sector number 1-63 (bits 0-5)
#			high two bits of cylinder (bits 6-7, hard disk only) 
#		DH = 8A head number
#		DL = 80, drive number (bit 7 set for hard disk)
#
#
#		CHANGING D00:00142 TO USE INTERRUPT 33 INSTEAD OF 13
#		one, two, three ... LOTS .. 
#		NOTE2XP: make NOTE out of this.
#
#SEE *IMPORTANT* NOTE1
]
[blank screen]
[real mode]
[
#	2000:0000062B CD13             INT         13
#		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			CX = FEFF, max 255 sectors, max 254 cylinders
#			DX = FE01, max 254 heads,   1 drive
#	2000:00000EBD CD13             INT         13
#		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
#		BX = 55AAh, The Magic Number 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			BX = AA55h, extension installed
#			AH = 21, 2.1 / EDD-1.1
#			CX = 5 = 101(b), 
#				extended disk *access* functions SUPPORTED
#				*removable* functions NOT supported
#				*EDD* functions SUPPORTED
#		SEE NOTE0
#	2000:00000EEC CD13             INT         13
#		AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		result
#		      DS:SI = 609C:000C
#		      609C:000C 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
#		      609C:001C 80 A7 54 02 00 00 00 00 00 02 00 00 00 00 00 00
#	2000:0000062B CD13             INT         13
#		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
#		AL = 1,  number of sectors to read (must be nonzero)
#		CH = 00, low eight bits of cylinder number
#		CL = 01, sector number 1-63 (bits 0-5)
#			high two bits of cylinder (bits 6-7, hard disk only) 
#		DH = 00 head number
#		DL = 80, drive number (bit 7 set for hard disk)
#
#lots of repeated calls
#or standard "code rewrite"
#
#13cd -> 33cd
#
#	62b
#	ebd
#	eec
#
#SEE *IMPORTANT* NOTE2
]
	1000:00005CD2 CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return
			AH=03h , fixed disk
			CX:DX = 00FA:0C53F, number of 512b blocks
	1000:00005CE3 CD13             INT         13
		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			CX = FEFF, max 255 sectors, max 254 cylinders
			DX = FE01, max 254 heads,   1 drive
	1000:00005CD2 CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DL=81h ,10000000(b) -> bit 7 on -> hard disk, 2nd hdd.
		return
			AH=00h , no such drive.
		SEE NOTE3
	1000:000054CA CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DL=00, floppy
		return
			AH=00, no such drive.

		xxxxxxxxxxxxxxx
		different exit? diff bios call? 

	1000:00005B29 CD13             INT         13
		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
		AL = 1,  number of sectors to read (must be nonzero)
		CH = 00, low eight bits of cylinder number
		CL = 01, sector number 1-63 (bits 0-5)
			high two bits of cylinder (bits 6-7, hard disk only) 
		DH = 00 head number
		DL = 80, drive number (bit 7 set for hard disk)
	1000:00005D45 CD13             INT         13
		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
		BX = 55AAh, The Magic Number 
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		return:
			BX = AA55h, extension installed
			AH = 21, 2.1 / EDD-1.1
			CX = 5 = 101(b), 
				extended disk *access* functions SUPPORTED
				*removable* functions NOT supported
				*EDD* functions SUPPORTED
		SEE NOTE0
	1000:00005D73 CD13             INT         13
		AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS 
		DL=80h ,10000000(b) -> bit 7 on -> hard disk
		result
			DS:SI = 16F3:0D0A
		16F3:00000D0A 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
		16F3:00000D1A 80 A7 54 02 00 00 00 00 00 02 28 00 00 00 80 00 
[
#
#	2000:0000062B CD13             INT         13
#		AH=08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			CX = FEFF, max 255 sectors, max 254 cylinders
#			DX = FE01, max 254 heads,   1 drive
#	2000:00000EBD CD13             INT         13
#		AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK
#		BX = 55AAh, The Magic Number 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		return:
#			BX = AA55h, extension installed
#			AH = 21, 2.1 / EDD-1.1
#			CX = 5 = 101(b), 
#				extended disk *access* functions SUPPORTED
#				*removable* functions NOT supported
#				*EDD* functions SUPPORTED
#		SEE NOTE0
#	2000:00000EEC CD13             INT         13
#		AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS 
#		DL=80h ,10000000(b) -> bit 7 on -> hard disk
#		result
#		      DS:SI = 609C:000C
#		      609C:000C 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
#		      609C:001C 80 A7 54 02 00 00 00 00 00 02 00 00 00 00 00 00
#	2000:0000062B CD13             INT         13
#		AH = 02, DISK - READ SECTOR(S) INTO MEMORY
#		AL = 1,  number of sectors to read (must be nonzero)
#		CH = 00, low eight bits of cylinder number
#		CL = 01, sector number 1-63 (bits 0-5)
#			high two bits of cylinder (bits 6-7, hard disk only) 
#		DH = 00 head number
#		DL = 80, drive number (bit 7 set for hard disk)

#SEE *IMPORTANT* NOTE2
]
[windows fully running, with "Start" button]
[no more interrupt 13h]

NOTE0:

we are using AMI BIOS (3/8/1) for most of the test so some of the description differs from what is said in the manual for the PHOENIX BIOS which I have used as primary reference. Such example is Int 13/AH=41 -- check for extensions.

NOTE1:

one, two, three, four...
LOTS of times....
probably something upwards of 200 times.

Argh. .stupidity of windows.. First it probes for extended disks read (meaning it can read up to 256 blocks at time), and then ..... READS ONE BLOCK AT TIME!

About the Flow, see Image below (click on it to enlarge).
There are two loops. The inner loop is inside of the "red" function. Then there is an outer loop inside of the "green" function.

The outer loop executes approximately 17 times (0x10). Inner loop executes around 1-2 times.

If you are going to trace code, once you get to address 7CB2 (top of "green" function) just disable all breakpoints and go to 80D6 (bottom of "green" function") and press F4 (go to cursor). This will just skip all 200+ invocations of this particular interrupt. Then re-enable all breakpoints again.

FlowChar of Interrupt 15 at 0000:00007D26

NOTE2:

        2000:0000061F CD13             INT         13
                AH = 08, DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,E$
                AH = 02, DISK - READ SECTOR(S) INTO MEMORY  
        2000:000006F3 CD13             INT         13
                AH = 42, IBM/MS INT 13 Extensions - EXTENDED READ
        2000:00000FE1 CD13             INT         13
                AH = 41,IBM/MS INT 13 Extensions - INSTALLATION CHECK  
        2000:00001010 CD13             INT         13
                AH = 48,IBM/MS INT 13 Extensions - GET DRIVE PARAMETER$

The above 4 functions are used extensively in Windows to read data off disk, even while in protected mode. What they have done is written 4 wrappers around those 4 functions which will switch from protected mode into real mode, execute 16 bit interrupt in one of those 4 functions, get data and then switch back to protected mode.

Since, as I have said, those functions are used extensively they make it difficult to see where else the interrupt line is used outside those 4 places.

Thus, it makes sense to rewrite windows and vector table to re-route those 4 functions to call INT13 code via different interrupt.

First, we pick some unused interrupt. Here I decided for interrupt 33h (address CCh in vector table). Thus, we are going to change the Vector Table as follows:

		int #	addr 	contest at the addr
	
	INT	13h	4C	F00:EED2

	INT	33h	CC	F00:5CB0
		replace above with below
	INT	33h	CC	F00:EED2

	in other words (16 bit-wide view of memory)

	0000:00CC	5CB0
		replace above with below
	0000:00CC	EED2

Second we need to update Windows code to call interrupt 33h instead of 13h. That is:

        2000:0000061F CD13             INT         13
		replace above with below
        2000:0000061F CD33             INT         33

        2000:000006F3 CD13             INT         13
		replace above with below
        2000:000006F3 CD33             INT         33

        2000:00000FE1 CD13             INT         13
		replace above with below
        2000:00000FE1 CD33             INT         33

        2000:00001010 CD13             INT         13
		replace above with below
        2000:00001010 CD33             INT         33


This all lets us get those 4 functions out of the way and see where else INT13 is used.

Finally like it or not, I will have to disable breakpoints on "start of interrupt" and "end of interrupt", and just leave breakpoint on entry in vector table alone (that is "Data Access" breakpoint at 4ChP).

It might potentially make us miss some important data, but hopefully that is not the case.

Then press F5 (continue) and as soon as it triggers breakpoint (which will be outside of the scope of the code I have modified) just re-enable all "start" and "end" breakpoints.


NOTE3:
	It is weird interrupt call. 

	Unlike "normal" call its DL argument is set to 81h
	instead of usual 80h.

	What I think is going on is that it is trying to
	probe for 2nd hard disk.

	Perhaps because of this, it calls itself again from
	inside of interrupt call. The call occurs at this line:

		F144:00000341 2EFF1E1901       CALL        dword ptr CS:[0119]
		CS:F144

	The bottom line is that, "end of interrupt" line is 
	executed twice.


NOTE4:
	[windows shutdown]
	[reboot]

NOTE5:
	as per BIOS manual:

	If not hdd is present. it (int13) is diskette/floppy 
	interrupt. However, if hdd is present it is "fixed disk" 
	interrupt and floppy has been reassigned to int 40.

	SO.. it is interrupt for HDD/fixed disk.

NOTE6:
	WOW, 16 bit BIOS calls from inside of protected mode...
	whee!

	it does jut gazillion times . switch from protected mode
	to real mode just so that it can make 16 bit BIOS 
	interrupt calls.
NOTE7:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

14 BIOS Serial Interface

ADDR	NT	INT	Description 				Status 
 50	0/0	14 	BIOS Serial Interface 			Supported 
VECTOR TABLE:
		0000:0050 F000:E739
BIOS (AMI):
	start	F000:E739 E9D711           JMP  near16 ptr 0000f913
	end	?????
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5   REP MOVS    dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+50h (ESI+50)
[windows fully running, with "Start" button]
[no more interrupt 14h]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 14h]
NOTE0:
	windows shutdown
	[reboot]

NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

15 BIOS System Functions Interface

ADDR	NT	INT	Description 				Status 
 54	??/11	15 	BIOS System Functions Interface 	Supported 
VECTOR TABLE:
		0000:0054 F000:F859
BIOS (AMI):
	start	F000:F859 E9247B           JMP  near16 ptr 00007380
	end	F000:8739 CA0200           RETF 0002
	end2	F000:AC83 CA0200           RETF 0002
	end3	F000:8703 CF               IRET        
	end4	F000:86FD CA0200           RETF 0002
	end5	F000:AECD CA0200           RETF 0002

WINDOWS 2000:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
SEE *IMPORTANT* NOTE0
[blank screen, with cursor at left top corner]

	2000:00001222 CD15             INT         15
		AH = C0, SYSTEM - GET CONFIGURATION (AT mdl 3x9,CONV,XT286,PS)
		
	2000:000004F3 CD15             INT         15
		AX = E820h, Newer BIOSes - GET SYSTEM MEMORY MAP
		EDX = 534D4150h ('SMAP')
		return
			EAX = 534D4150h ('SMAP')

		one, two, three, four, five, six, seven
[cursor at left top corner gone, ALL blank screen]
	2000:00000E8D CD15             INT         15
		AX = E820h, Newer BIOSes - GET SYSTEM MEMORY MAP
		EDX = 534D4150h ('SMAP')
		return
			EAX = 534D4150h ('SMAP')

		one, two, three, four, five, six

	1000:0000448A CD15             INT         15
		AH = C0, SYSTEM - GET CONFIGURATION (AT mdl 3x9,CONV,XT286,PS)
	1000:00004686 CD15             INT         15
		AH = C0, SYSTEM - GET CONFIGURATION (AT mdl 3x9,CONV,XT286,PS)
	1000:000044CD CD15             INT         15
		AH = C0, SYSTEM - GET CONFIGURATION (AT mdl 3x9,CONV,XT286,PS)

		one, two

	1000:00004518 CD15             INT         15
		AH = C0, SYSTEM - GET CONFIGURATION (AT mdl 3x9,CONV,XT286,PS)

	1000:0000011B CD15             INT         15
		AX = 5300h, Advanced Power Management v1.0+ -INSTALLATION CHECK
		BX = 0000h, device ID of system BIOS (0000h)
		return
			AH = 01, major version (BCD)
			AL = 02, minor version (BCD)
			BX = 504Dh ("PM")
			CX = 3, 11(b) - 
				0     16-bit protected mode interface supported
				1     32-bit protected mode interface supported
		SEE *IMPORTANT* NOTE1
	1000:00001BC4 CD15             INT         15
		AH = C0, return system parameters
	1000:000050B0 CD15             INT         15
		AH = C1, Return Extended BIOS Data Area Address
		return
		      ES = ???, Segment of EBDA
		      Carry = 1, ERROR
		      AH = 86, Invalid BIOS routine Call (No EBDA)
		SEE NOTE4
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+54h (ESI+54)
[windows fully running, with "Start" button]
[no more interrupt 15h]
WINDOWS XP:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
SEE *IMPORTANT* NOTE0
[blank screen, with cursor at left top corner]

	2000:000004F3 CD15             INT         15
		AX = E820h, Newer BIOSes - GET SYSTEM MEMORY MAP
		EDX = 534D4150h ('SMAP')
		return
			EAX = 534D4150h ('SMAP')

		one, two, three, four, five, six, seven
[cursor at left top corner gone, ALL blank screen]
	2000:00000D69 CD15             INT         15
		AX = E820h, Newer BIOSes - GET SYSTEM MEMORY MAP
		EDX = 534D4150h ('SMAP')
		return
			EAX = 534D4150h ('SMAP')

		one, two, three, four, five,six
	1000:0000011B CD15             INT         15
		AX = 5300h, Advanced Power Management v1.0+ -INSTALLATION CHECK
		BX = 0000h, device ID of system BIOS (0000h)
		return
			AH = 01, major version (BCD)
			AL = 02, minor version (BCD)
			BX = 504Dh ("PM")
			CX = 3, 11(b) - 
				0     16-bit protected mode interface supported
				1     32-bit protected mode interface supported
	1000:0000011B CD15             INT         15
		AX = 5301h, Advanced Power Management v1.0+ - 
				CONNECT REAL-MODE INTERFACE
		BX = 0000h, device ID of system BIOS (0000h)
	1000:0000011B CD15             INT         15
		AX = 530Eh, Advanced Power Management v1.1+ - DRIVER VERSION
		BX = 0000h, device ID of system BIOS (0000h)
		CH = 01, APM driver major version (BCD)
		CL = 02, APM driver minor version (BCD) (02h for APM v1.2)
		Return:
			CF = 00 ,clear if successful 
			AH = 01, APM connection major version (BCD) 
			AL = 02, APM connection minor version (BCD) 
	1000:0000011B CD15             INT         15
		AX = 5300h, Advanced Power Management v1.0+ -INSTALLATION CHECK
		BX = 0000h, device ID of system BIOS (0000h)
		return
			AH = 01, major version (BCD)
			AL = 02, minor version (BCD)
			BX = 504Dh ("PM")
			CX = 3, 11(b) - 
				0     16-bit protected mode interface supported
				1     32-bit protected mode interface supported
	1000:0000011B CD15             INT         15
		AX = 5304h, Advanced Power Management v1.0+ -
				DISCONNECT INTERFACE
		BX = 0000h, device ID of system BIOS (0000h)
	1000:0000011B CD15             INT         15
		AH = 5302h, Advanced Power Management v1.0+ - 
				CONNECT 16-BIT PROTMODE INTERFACE
		BX = 0000h, device ID of system BIOS (0000h)
		Return:
			CF = 00,clear if successful 
			AX = F000h, real-mode segment base address of 
				    protected-mode 16-bit code segment 
			BX = EF4Dh, offset of entry point 
			CX = 0040h, real-mode segment base address of 
				    protected-mode 16-bit data segment 
					---APM v1.1--- 
			SI = 0E22h, APM BIOS code segment length 
			DI = 0100h, APM BIOS data segment length 
	1000:0000011B CD15             INT         15
		AX = 530Eh, Advanced Power Management v1.1+ - DRIVER VERSION
		BX = 0000h, device ID of system BIOS (0000h)
		CH = 01, APM driver major version (BCD)
		CL = 02, APM driver minor version (BCD) (02h for APM v1.2)
		Return:
			CF = 00 ,clear if successful 
			AH = 01, APM connection major version (BCD) 
			AL = 02, APM connection minor version (BCD) 

	1000:00002764 CD15             INT         15
		AH = C0, SYSTEM - GET CONFIGURATION (AT mdl 3x9,CONV,XT286,PS)
	1000:00006D0B CD15             INT         15
		AH = C1, SYSTEM - RETURN EXTENDED-BIOS DATA-AREA 
		return
		      ES = ????, Segment of EBDA
		      Carry = 1, ERROR
		      AH = 86, Invalid BIOS routine Call (No EBDA)
		SEE NOTE4
[windows fully running, with "Start" button]
[no more interrupt 15h]


NOTE0:

Interrupt 15 is used internally by Interrupt 13. That is BIOS is using Interrupt 15 internally for its own needs.

This means that we have to rewrite c) Vector Table and d) BIOS, so that they use a different interrupt for communication. It is sort of similar to "fix-up" we used in Interrupt 13 except that the "other end" is BIOS and not Windows source. This makes necessary for us to perform one extra step before we can go about and fix code.

We have to make BIOS code Read-Write. By the default it is read only. In order to do that we need to: a) Make sure that BIOS is shadowed into RAM, and then b) setup that portion of RAM Read/Write.

  • a) To make sure BIOS is shadowed into RAM, check BIOS setup. that is an configuration option there, something looking like :
    Shadow BIOS: Enabled
  • b) we issue appropriate commands to the North Bridge to make that ram Read-Write. For details see:
    Shadow BIOS
    in general the whole magic boils down to those two commands:
    		dport 0CF8h = 80000070h
    		wport 0CFEh = 1000h
    	
    Once we have done that, we go about fixing code. This boils down to those two steps:
  • c) fixing Vector Table as show below:
    	0000:0054P F000:F859
    	0000:00CCP F000:5CB0
    		replace above with below
    	0000:00CCP F000:F859
    	
  • d) modifying BIOS code.
    • 	F144:000009CB CD15             INT         15
      		replace above with below
      	F144:000009CB CD33             INT         33
      	
      and
    • 	F000:0000E861 CD15             INT         15
      		replace above with below
      	F000:0000E861 CD33             INT         33
      	
  • e) Finally make that area of ram Read-Only once again
    		wport 0CFEh = 0000h
    	

	Now interrupt is rerouted. :-)

	For record: here is structure of the Internal call
	as used by  BIOS:

	F144:000009CB CD15             INT         15
		AH = 90, device busy
		AL = 00, fixed disk

		by the way of interrupt 13/AH=42, disk read
			0000:00007D26 CD13             INT         13

		repeats 5++ times. need to rewrite int 13 handler.

	F000:0000E861 CD15             INT         15
		AH=91, interrupt complete
		AL=00, fixed disk


NOTE1:
	NOTE: this comment only applies to windows 2000. I believe I
	got APM stuff right in the Windows XP.

	NOTE: those stuff in regards of APM are just approximate.
	APM code is weird and confused my debugger to hell requiring
	*EVERYTHING* (Host,Target,and In-Target Probe) to be hard reset.
	
	so the list of APM interrupts/calls might be wrong.

	there is lots of callback or direct calls.

	There is lots of internal BIOS calls going on there.

	for one thing you probably want to disable ALL
	breakpoints when stepping through the interrupt.

	some calls I saw:
		AH=53
			AL = 00,
			AL = 01, Interface connect
			AL = 02,
			AL = 04,
			AL = 0E, APM Driver Version (APM 1.1 only)

	There will be even more different calls when APM is enabled.

NOTE2:
	when you *ENABLE* APM there will extra APM calls take 
	place. Perhaps it will include this one as well.

	1000:0000011B CD15             INT         15
		AH=F0, ?????, engage/disengage power management

NOTE3:
	windows shutdown
	[reboot]

NOTE4:

       This Interrupt/Function (15/C1) is used to query Extended
       BIOS Data Area (EBDA). You can check out section 3.4 for more 
       details.

       In our case the interrupt seems to return error that 
       this function is not supported. This is most likely
       because we have disabled PS/2 mouse in BIOS. The 
       EBDA is used pretty much exclusively for PS/2 mouse 
       only, so once it is disabled there's not much of point
       having EDBA in use.

NOTE5:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.
		- small differences of offset in a segment.

	major differences:
		- does not do one interrupt call at beginning anymore.
		- does far less interrupt calls with arg AH=C0 and AH=C1

16 BIOS Keyboard Interface

ADDR	NT	INT	Description 				Status 
 58	12/5	16(22d) BIOS Keyboard Interface 		Supported 
VECTOR TABLE:
		0000:0058 F000:E82E 
BIOS (AMI):
	start	F000:E82E E9C3B2           JMP   near16 ptr 00009af4
	end	F000:9BBC CA0200           RETF  0002
	end2	F000:9B28 CF               IRET    
			AH=02
WINDOWS 2000:
[blank screen, real mode]
	2000:0000075D CD16             INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
	1000:00001C59 CD16             INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
	1000:00001D74 CD16             INT         16
		AH=02, KEYBOARD - GET SHIFT FLAGS
		return
			AL=20 = 10100(b) = flags 
				5= Num Lock on, 
				3=Alt pressed (?????)
	1000:00001C59 CD16             INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
["Starting Windows", real mode]
[stripe is "4" full]
	2000:0000075D CD16             INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available

		one, two, three, four, five, six, seven, eight
[windows graphic screen shows up (the "window flag"), protected mode]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5   REP MOVS    dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+58h (ESI+58)
[windows fully running, with "Start" button]
[no more interrupt 16h]
WINDOWS XP:
[blank screen, real mode]
	2000:00000769 CD16        INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
	1000:000027F9 CD16        INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
	1000:00002914 CD16        INT         16
		AH=02, KEYBOARD - GET SHIFT FLAGS
		return
			AL=20 = 10100(b) = flags 
				5= Num Lock on, 
				3=Alt pressed (?????)
	1000:000027F9 CD16        INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
		[again]
	2000:00000769 CD16        INT         16
		AH=01, KEYBOARD - CHECK FOR KEYSTROKE
		return
			ZF=1, no keystroke available
		[again]
[windows fully running, with "Start" button]
[no more interrupt 16h]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	for reference, 

	here is example how Int 16 is used/setup inside of bios/lilo/win
	this example/roadmap is for Phoenix BIOS

	BIOS:
		F000:0000E2CD : zero vector table
		F000:0000E2E1 : test zeroing VT was successful
		F000:00001B1B : set all interrupts to F000:E816
		F000:00001B35 : set kbd interrupt  to F000:E82E
		F000:00002A6A : load all vector table into single reg ?????
			first BIOS screen shows up
		F000:0000BC58 : some memory comparison/verification 
			after HDD probe
			after PCI probe
				repeats 4 times total
	LILO:	
		structure of interrupt call to KBD when LILO starts
			vector	0000:00000040 C00007CB 
			code    F000:0000E82E EB01   - JMP - short ptr 0000e831
 			end     F000:0000E891 CA0200 - RETF 0002

		first interrupt call : "LI"
			0B00:0000008A CD16             INT         16
		second interrupt call : "LILO boot: _", press enter
			0B00:00000918 CD16             INT         16
			repeats 3 times
	windows
		blank screen
			2000:0000075D CD16             INT         16
			1000:00001C59 CD16             INT         16
			1000:00001C59 CD16             INT         16

			//1000:00001D74 CD16             INT         16
		4 unmodified interrupt calls
	
NOTE2:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.
		- small differences of offset in a segment.

	major differences:
		- does six less interrupt calls with arg AH=01

17 BIOS Parallel Printer Interface

ADDR	NT	INT	Description 				Status 
 5C	0/0	17 	BIOS Parallel Printer Interface 	Supported 
VECTOR TABLE:
		0000:005C F000:D08B
BIOS (AMI):
	start	F000:D08B 3D0002           CMP   AX,0200
	end	?????
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+5Ch (ESI+5C)
[windows fully running, with "Start" button]
[no more interrupt 17h]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 17h]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	Since parallel port is disabled,in BIOS, this interrupt is "used" only 
	one time (read) instead of three times before.
NOTE2:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

18 BIOS Secondary Boot Request

ADDR	NT	INT	Description 				Status 
 60	0/0	18 	BIOS Secondary Boot Request 		Supported 
VECTOR TABLE:
		0000:0060 F000:E000
BIOS (AMI):
	start	F000:E000 EA05E000F0       JMP  far16 ptr f000:0000e005
	end	?????
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+60h (ESI+60)
[windows fully running, with "Start" button]
[no more interrupt 18h]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 18h]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

19 BIOS Primary Boot Request

ADDR	NT	INT	Description 				Status 
 64	0/0	19 	BIOS Primary Boot Request 		Supported 
VECTOR TABLE:
		0000:0064 F000:881E
BIOS (AMI):
	start	F000:881E 2E833EDEF600     CMP  word ptr CS:[f6de],0000
	end	?????
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5   REP MOVS    dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+64h (ESI+64)
[windows fully running, with "Start" button]
[no more interrupt 19h]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 19h]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

1A BIOS System Timer Interface

ADDR	NT	INT	Description 				Status 
 68	12/13	1A 	BIOS System Timer Interface 		Supported 
VECTOR TABLE:
		0000:0068 F000:FE6E
BIOS (AMI):
	start	F000:FE6E E91B5F           JMP  near16 ptr 00005d8c
	end	F000:9C28 CA0200           RETF  0002
	end2	F000:5DAA CF               IRET     
WINDOWS 2000:
[blank screen, real mode]
	2000:000007C4 CD1A             INT         1a
		AH=00h, TIME - GET SYSTEM TIME
		return:
			CX:DX = number of clock ticks since midnight 
			AL = midnight flag, nonzero if midnight passed 
				since time last read 
		one,two
	1000:00005671 CD1A             INT         1a
		AX  = B101h, PCI BIOS v2.0c+ - INSTALLATION CHECK
		EDI = 00000000h
		return:
			AH  = 00h,installed 
			EDX = 20494350h (' ICP') 
			EDI = 0h, physical address of protected-mode entry 
					point (see #00731) 
			AL = 01h, PCI hardware characteristics (see #00730) 
				0 - configuration space access mechanism 1 
					supported
			BH = 02h, PCI interface level major version (BCD) 
			BL = 10h, PCI interface level minor version (BCD) 
			CL = 01h, number of last PCI bus in system 

	1000:000056EB CD1A             INT         1a
		AX = B10Eh, PCI BIOS v2.1+ - GET IRQ ROUTING INFORMATION
		BX = 0000h
		DS = F000h, segment/selector for PCI BIOS data
		one, 
		return:
			BX = 00h,
			CF = 1
			AH = 89h, buffer too small
		two
		return:
			BX = 00h, bit map of IRQ channels 
				permanently dedicated to PCI
			CF = 0
			AH = 00h, Successful
	2000:000007C4 CD1A             INT         1a
		AH=00h, TIME - GET SYSTEM TIME
		return:
			CX:DX = number of clock ticks since midnight 
			AL = midnight flag, nonzero if midnight passed 
				since time last read 
["Starting Windows", real mode]
[stripe is "4" full]
	2000:000007C4 CD1A             INT         1a
		AH=00h, TIME - GET SYSTEM TIME
		return:
			CX:DX = number of clock ticks since midnight 
			AL = midnight flag, nonzero if midnight passed 
				since time last read 
		one,two,three,four,five,six?????
[windows graphic screen shows up (the "window flag"), protected mode]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+68h (ESI+68)
[windows fully running, with "Start" button]
[no more interrupt 1Ah]
WINDOWS XP:
[blank screen, real mode]
	2000:000007D0 CD1A        INT         1a
		AH=00h, TIME - GET SYSTEM TIME
		return:
			CX:DX = number of clock ticks since midnight 
			AL = midnight flag, nonzero if midnight passed 
				since time last read 
		one,two
	1000:00007661 CD1A        INT         1a
		AX  = B101h, PCI BIOS v2.0c+ - INSTALLATION CHECK
		EDI = 00000000h
		return:
			AH  = 00h,installed 
			EDX = 20494350h (' ICP') 
			EDI = 0h, physical address of protected-mode 
					entry point (see #00731) 
			AL = 01h, PCI hardware characteristics (see #00730) 
				0 - configuration space access mechanism 1 
					supported
			BH = 02h, PCI interface level major version (BCD) 
			BL = 10h, PCI interface level minor version (BCD) 
			CL = 01h, number of last PCI bus in system 

	1000:000076DB CD1A        INT         1a
		AX = B10Eh, PCI BIOS v2.1+ - GET IRQ ROUTING INFORMATION
		BX = 0000h
		DS = F000h, segment/selector for PCI BIOS data
		one, 
		return:
			BX = 00h,
			CF = 1
			AH = 89h, buffer too small
		two
		return:
			BX = 00h, bit map of IRQ channels permanently 
					dedicated to PCI
			CF = 0
			AH = 00h, Successful
	2000:000007D0 CD1A        INT         1a
		AH=00h, TIME - GET SYSTEM TIME
		return:
			CX:DX = number of clock ticks since midnight 
			AL = midnight flag, nonzero if midnight passed 
				since time last read 
		one,two,three,four,five,six,seven,eight
[windows fully running, with "Start" button]
[no more interrupt 1Ah]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.
		- more streamlined start.

1B BIOS Control Break Interrupt

ADDR	NT	INT	Description 				Status 
 6C	0/0	1B 	BIOS Control Break Interrupt 		Supported 
VECTOR TABLE:
		0000:006C F000:FF53
BIOS (AMI):
	start	F000:FF53 CF               IRET        
	end	F000:FF53 CF               IRET        
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+6Ch (ESI+6C)
[windows fully running, with "Start" button]
[no more interrupt 1Bh]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 1Bh]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	**Important**

	Both Interrupt 1C and Interrupt 1B share the same 
	"Interrupt Service Routine" (ISR).

	Yes, it just happen to be an one-liner which does 
	only one thing. Just calls "IRET".

	However, an important implication of this is that
	If I will try to trace interrupt 1B by setting 
	breakpoints on Entry and Exit from Interrupt Routine, 
	I will instead trip on interrupt calls to Interrupt 1C.
NOTE2:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

1C BIOS User System Timer Interrupt

ADDR	NT	INT	Description 				Status 
 70	0/0	1C 	BIOS User System Timer Interrupt 	Supported 
VECTOR TABLE:
		0000:0070 F000:FF53
BIOS (AMI):
	start	F000:FF53 CF               IRET        
	end	F000:FF53 CF               IRET        
WINDOWS 2000:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
SEE *IMPORTANT* NOTE1
	2000:00000D22 8B0D             MOV         CX,word ptr [DI]
	2000:00000D24 8B5502           MOV         DX,word ptr [DI]+2
		CX = FF53h
		DX = F000h
		DI = 70h
		save vector for Int 1C into CX register
	2000:00000D2A 8905             MOV         word ptr [DI],AX
	2000:00000D2E 894502           MOV         word ptr [DI]+02,AX
		DI = 70h, 
		AX = 0D73h,
		AX = 2000h,
		setup new interrupt handler
	2000:00000D63 890D             MOV         word ptr [DI],CX
	2000:00000D65 895502           MOV         word ptr [DI]+02,DX
		DI = 70h, 
		CX = FF53h,
		DX = F000h,
		restore old interrupt handler
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+70h (ESI+70)
[windows fully running, with "Start" button]
[no more interrupt 1Ch]
WINDOWS XP:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
SEE *IMPORTANT* NOTE1
	2000:0BFE 8B0D   MOV CX,word ptr [DI]
	2000:0C00 8B5502 MOV DX,word ptr [DI]+2
		CX = FF53h
		DX = F000h
		DI = 70h
		save vector for Int 1C into CX register
	2000:0C06 8905   MOV word ptr [DI],AX
	2000:0C0A 894502 MOV word ptr [DI]+02,AX
		DI = 70h, 
		AX = 0C4Fh,
		AX = 2000h,
		setup new interrupt handler
	2000:0C3F 890D   MOV word ptr [DI],CX
	2000:0C41 895502 MOV word ptr [DI]+02,DX
		DI = 70h, 
		CX = FF53h,
		DX = F000h,
		restore old interrupt handler
[windows fully running, with "Start" button]
[no more interrupt 1Ch]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:

Interrupt 1C is being called from inside of System Timer Interrupt (Interrupt 08) on every clock tick. In other words huge number of times :-)

	Interrupt 08:
		F000:0000FEA5 E9C7E1           JMP         near16 ptr 0000e06f
		        F000:0000E0B7 CD1C             INT         1c
		F000:0000E0C1 CF               IRET

It means we have to rewrite BIOS code once again.

See

Interrupt 15 and Shadow BIOS

for details on how to make Shadow RAM Read/Write.

Next. Since the "code handler" for Interrupt 1C seems to be just one-liner "IRET" we can assume it is probably safe to simply "eliminate" this call from inside of Interrupt Service Routine (ISR) for Interrupt 8. Thus we would be replacing code for "INT 1C" with two NO-OP instructions.

That is:

		
		F000:0000E0B7 CD1C             INT         1c	
			replace above with the two below
		F000:0000E0B7 90		NOP
		F000:0000E0B8 90		NOP
		

If I do above change, it seems to get stuck in this loop

2000:
		2000:00000D4F 6683FB00         CMP         EBX,00000000
		2000:00000D53 74FA             JE          short ptr 00000d4f
XP:
		2000:00000C2B 6683FB00         CMP         EBX,00000000
		2000:00000C2F 74FA             JE          short ptr 00000d4f

Setting EBX to 01h gets it out of this loop. Then it stars-up, but more slowly than usual (there is at least one loop, in windows code, that needs to time out). Overall works, but slower. I'm not sure of the reason for slow-down.

Experiment trying to reroute the call from interrupt 08 to "IRET" at F000:FF53 via Interrupt CCh (in similar way as we did for Interrupt 15 , for example) does not seem to work. it seems to hang somewhere in BIOS. I am not sure what to make out of this. Perhaps there's going on some dirty magic in background which implicitly makes it depend on 1C.

NOTE2:

As start/end [of interrupt] show it is just "dummy" interrupt. Thus the only "implementation requirement" is that it is be called from int 8 every tick, and then just execute IRET.

NOTE3:

**Important**

Both Interrupt 1C and Interrupt 1B share the same "Interrupt Service Routine" (ISR).

Yes, it just happen to be an one-liner which does only one thing. Just calls "IRET".

However, an important implication of this is that If I will try to trace interrupt 1B by setting breakpoints on entry and exit from the routine, I will instead trip on interrupt calls to Interrupt 1C. On the same token, attempts to trace interrupt 1C might get polluted by use of interrupt 1B (thought it does not seem to be case)

NOTE2:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

1D BIOS Video Init Parameters

ADDR	NT	INT	Description 				Status 
 74	0/0	1D 	BIOS Video Init Parameters 		Supported 
VECTOR TABLE:
		0000:0074 F000:F0A4
BIOS (AMI):
	start	F000:F0A4 3828             CMP  byte ptr [BX+SI],CH
	end	?????
WINDOWS 2000:
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+74h (ESI+74)
[windows fully running, with "Start" button]
[no more interrupt 1Dh]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 1Dh]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

1E BIOS Diskette Parameters

ADDR	NT	INT	Description 				Status 
 78	0/0	1E 	BIOS Diskette Parameters 		Supported 
VECTOR TABLE:
		0000:0078 F000:EFC7
BIOS (AMI):
	start	F000:EFC7 DF02             FILD word ptr [BP+SI]
	end	F000:F138 CF               IRET    
			?????
WINDOWS 2000:
[blank screen, real mode]
	2000:00001ED2 BB7800           MOV        BX,0078
	2000:00001ED5 268B07           MOV        AX,word ptr ES:[BX]
	2000:00001ED8 268B5702         MOV        DX,word ptr ES:[BX]+02
		ES=00h,
		AX=EFC7h,
		DX=F000h,
		load vector table entry for int 1E into DX:AX
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+78h (ESI+78)
[windows fully running, with "Start" button]
[no more interrupt 1Eh]
WINDOWS XP:
[windows fully running, with "Start" button]
[no more interrupt 1Eh]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	LILO:
		F144:00001CC2 C5367800         LDS         SI,word ptr [0078]
		?????		
NOTE1:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.
		- much simpler start. does not even do that extra save.

1F BIOS Video Graphic Characters

ADDR	NT	INT	Description 				Status 
 7C	0/0	1F 	BIOS Video Graphic Characters 		Supported 
VECTOR TABLE:
		0000:007C C000:7931
BIOS (AMI):
	start	C000:00007931 78CC             JS          short ptr 000078ff
	end	?????
WINDOWS 2000:
[blank screen, real mode]
SEE *IMPORTANT* NOTE1
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+7Ch (ESI+7C)
[windows fully running, with "Start" button]
[no more interrupt 1Fh]
WINDOWS XP:
[blank screen, real mode]
SEE *IMPORTANT* NOTE1
[windows fully running, with "Start" button]
[no more interrupt 1Fh]
NOTE0:
	[windows shutdown]
	[reboot]

NOTE1:
	The vector table entry is READ by the way of interrupt 10 call.

		1000:00001C88 CD10   INT   10
			C000:00006546 C43E7C00   LES   DI,word ptr [007c]

	one, two, three, four, five, six
NOTE2:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

40 BIOS Diskette (when fixed disk present) Supported

ADDR	NT	INT	Description 				Status 
100	0/0	40 	BIOS Diskette (when fixed disk present) Supported 
VECTOR TABLE:
		0000:0100 F000:EC59
BIOS (AMI):
	start	F000:EC59 E9DF01           JMP near16 ptr 0000ee3b
	end	F144:1C40 CF               IRET
WINDOWS 2000:
[blank screen, real mode]
SEE *IMPORTANT* NOTE2
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+100h (ESI+100)
[windows fully running, with "Start" button]
[no more interrupt 40h]
WINDOWS XP:
[blank screen, real mode]
SEE *IMPORTANT* NOTE2
[windows fully running, with "Start" button]
[no more interrupt 40h]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	LILO:
		an call by the way of interrupt 13
	
			once, twice

NOTE2:

	This interrupt was called once by the way of interrupt 13.
	See Interrupt 13 for more details on this call.

	1000:00003989 CD13             INT         13
		AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
		DL=00, A: floppy (?????)
		return:
			AH=00, no such drive.

		F144:000003EF CD40             INT         40
			AH=15, DISK - GET DISK TYPE (XT286,AT,PS)
			DL=00	
			return 
				AH=00, no such drive.
		F144:00001C40 CF               IRET
	F144:000003F1 CA0200           RETF        0002
NOTE3:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

41 BIOS Fixed disk 0 parameters

ADDR	NT	INT	Description 				Status 
104	0/0	41 	BIOS Fixed disk 0 parameters 		Supported 
VECTOR TABLE:
		0000:0104 F144:0040
BIOS (AMI):
	start	F144:0040 0004             ADD byte ptr [SI],AL
	end	?????
WINDOWS 2000:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
SEE *IMPORTANT* NOTE2
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+74h (ESI+74)
[windows fully running, with "Start" button]
[no more interrupt 41h]
WINDOWS XP:
["LILO boot:\r\nLoading winblows" text still visible]
[real mode]
SEE *IMPORTANT* NOTE2
[windows fully running, with "Start" button]
[no more interrupt 41h]
NOTE0:
	[windows shutdown]
	[reboot]

NOTE1:
	SYSTEM DATA - HARD DISK 0 PARAMETER TABLE ADDRESS [NOT A VECTOR!]

	It supposedly is not as much ISR as pointer to data 
	storage area for the first disk parameter table.

	For that matter, you might want to use "Data Access" breakpoint
	instead of usual "Execute" breakpoint at the address pointed 
	by the entry in the Vector Table (F144:40h here).


NOTE2:
	
	It is being read many times (each time) by the way of 
	Interrupt 13 call. The two relevant lines in ISR 13 
	are as shown below:

	(a)
		F144:000008FB 26C41F           LES         BX,word ptr ES:[BX]
			before:
				BX=0104h,
				ES=0000h
			after:
				BX=0040h,
				ES:F144h
	(b)
		F144:00000931 26AC             LODS        byte ptr ES:[SI]
			ES=F144h
			SI=0041h

	In regards of (a):

	To get around the first line (the one with LES instruction), we
	pick our favorite vector 33h (CCh in the Vector Table)

		int #	addr 	contest of the cell
	INT	33h	CCh	F000:5CB0
		replace above with below
	INT	33h	CCh	F144:0040
	INT	41h	104	F144:0040

	Next we edit BIOS code to use vector 33h instead of 41h.
	
	See Interrupt 15 and Shadow BIOS
	for details on how to make Shadow RAM Read/Write.

	The magic line is few lines before the LES instruction.

	F144:000008E7 BB0401           MOV         BX,0104

	Thus we do:

	F144:000008E7 BB0401           MOV         BX,0104
		replace above with below
	F144:000008E7 BBCC00           MOV         BX,00CC

	In regards of (b):

	In similar way we could get around second line (the one which
	uses "LODS" instruction). However this one being triggered
	only when we set up "Data Access" breakpoint on F144:0040h
	instead of usual "Execute" breakpoint on the said address.
	Thus we can get around this line by simply not setting that breakpoint.
	Furthermore, unlike the vector table changes, it would be not 
	as easy to setup alternative place where the LOAD instruction could
	refer to, so unselecting this break points is the best way to 
	deal with it.

NOTE3:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.

46 BIOS Fixed disk 1 parameters

ADDR	NT	INT	Description 				Status 
118	0/0	46 	BIOS Fixed disk 1 parameters 		Supported 
VECTOR TABLE:
		0000:0118 F144:0050
BIOS (AMI):
	start	F144:0050 3201             XOR AL,byte ptr [BX+DI]
	end	?????
WINDOWS 2000:
[blank screen,real mode]
SEE *IMPORTANT* NOTE2
[windows graphic screen shows up (the "window flag")]
[blue "Staring up" bar is full"]
[protected mode]
	0008:80401E22 F3A5    REP MOVS   dword ptr [EDI],dword ptr [ESI]
		saves vector table to ~ 360000+118h (ESI+118)
[windows fully running, with "Start" button]
[no more interrupt 46h]
WINDOWS XP:
[blank screen,real mode]
SEE *IMPORTANT* NOTE2
[windows fully running, with "Start" button]
[no more interrupt 46h]
NOTE0:
	[windows shutdown]
	[reboot]
NOTE1:
	SYSTEM DATA - HARD DISK 1 DRIVE PARAMETER TABLE ADDRESS [NOT A VECTOR!]

	It supposedly is not as much ISR as pointer to data 
	storage area for the second disk parameter table.

	For that matter, you might want to use "Data Access" breakpoint
	instead of usual "Execute" breakpoint at the address pointed 
	by the entry in the Vector Table (F144:50h here).


NOTE2:
	It is being read ONCE by the way of Interrupt 13 call.
	It is most likely query for the 2nd hard disk.
	
	2000:	
	1000:00003F72 CD13             INT         13
	XP:
	1000:00005CD2 CD13             INT         13
	
	AH=15, DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)
			DL=81h ,10000000(b) -> bit 7 on -> hard disk, ?????
			return
				AH=00h , no such drive.
			SEE NOTE3 for Interrupt 13

		F000:EED2 E961FF           JMP near16 ptr 0000ee36

		F144:000008FB 26C41F     LES         BX,word ptr ES:[BX]
				before:
					BX=0118h,
					ES=0000h
				after:
					BX=0050h,
					ES:F144h
		F144:0000035E CA0200           RETF        0002

NOTE3:
	If you setup "Data Access" breakpoint at F144:0050h 
	(instead of the usual "Execute" style breakpoint), you will get
	some more hits. 

	For 2000:

	Among other this one. Repeats around 5 times.

	1000:000045B2 26663B05         CMP         EAX,dword ptr ES:[DI]
		ES=F000
		DI=1490

	For XP:

	All of the below are some access to area pointed by the
	vector table entry (disk param area) and not the vector
	table itself. With the sole exception of indirect access
	via int 13 call.

	1000:00006F82 268A4707         MOV         AL,byte ptr ES:[BX]+07
	1000:00007FC2 268A07           MOV         AL,byte ptr ES:[BX]

	1000:00005CD2 CD13             INT         13
	        F144:0000035E CA0200           RETF        0002
	1000:0000840E 268A07           MOV         AL,byte ptr ES:[BX]
		[start of protected mode]
	001B:77F52DA8 8908             MOV         dword ptr [EAX],ECX
	001B:77F52CBF 8B08             MOV         ECX,dword ptr [EAX]
	001B:77F520EB F3AB             REP STOS    dword ptr [EDI]
	001B:77F81198 F3A5             REP MOVS    dword ptr [EDI],dword ptr [ESI]
	[windows up with a sand-clock user on screen]
	001B:77F56D1D 668B06           MOV         AX,word ptr [ESI]
		multiple hits...


	However, since there was no use of the vector table to ascertain
	that this particular region of memory is used for fixed disk,
	it does not seem likely those data accesses are related to 
	hard disk.

NOTE4:
	2000 vs XP

	The visible changes are in green.

	minor "standard" differences:
		- does not save vector table anymore.


3.1.4. BIOS Interrupts Usage Statistics

This table summarizes Interrupts usage for both Windows XP as well as Windows 2000. Results here are presented in tabular form which lists a) total number of times given address was accessed, then b) Total number times given address as used in form of interrupt call (as opposed to data read/write from given address), and finally total number of unique functions which had been used with given interrupt. What you really care for are just entries in RED.

Int

BIOS

Interrupt

Description

Total

Interrupt

Uses

Total

Interrupts

Calls

Total

Unique Interrupt

Calls

2000

XP

2000

XP

2000

XP

10

Video Interface

16

12

13

11

12

11

11

Equipment Check

2

1

1

1

1

1

12

Memory Request

1

0

0

0

0

0

13

Fixed Disk Interface

lots+1

lots

lots

lots

6

5

14

Serial Interface

1

0

0

0

0

0

15

System Functions Interface

~22+1

22

~22

22

~4+

8

16

Keyboard Interface

13

5

12

5

2

2

17

Parallel Printer Interface

1

0

0

0

0

0

18

Secondary Boot Request

1

0

0

0

0

0

19

Primary Boot Request

1

0

0

0

0

0

1A

System Timer Interface

13

13

12

13

3

3

1B

Control Break Interrupt

1

0

0

0

0

0

1C

User System Timer Interrupt

4

3

0

0

0

0

1D

Video Init Parameters

1

0

0

0

0

0

1E

Diskette Parameters

4

0

0

0

0

0

1F

Video Graphic Characters

1

0

0

0

0

0

40

Diskette Interface

1

0

0

0

0

0

41

Fixed disk 0 parameters

1

0

0

0

0

0

46

Fixed disk 1 parameters

1

0

0

0

0

0

"~" means approximate number
"+" means than there's more than given number of interrupts.


3.1.5. BIOS Interrupt Usage Summary

Windows 2000 and XP have very similar interrupt usage pattern. Thus there's no big difference in description/summary of them here. The notable differences are that XP won't use those Interrupt/Functions:

1000:00000000 CD10             INT         10
    AH=00 - VIDEO - SET VIDEO MODE
    AL=12 - 12h = G 80x30  8x16  640x480 16/256K . A000 VGA

2000:000006F3 CD13             INT         13
     AH = 42, IBM/MS INT 13 Extensions - EXTENDED READ
     DL=80h ,10000000(b) -> bit 7 on -> hard disk
Another benefit of XP over 2000 would be that it's APM implementation seems to be more sane/reasonable. I didn't have much of trouble trying to trace out XP's interaction with APM, while for 2000 it would hard-crash my whole testing system.

Having said it all, let's go over interrupts which are used by both versions of windows, and have similar pattern of usage.

We start off with the full vector table.

Next we nail it down to a list of 19 "BIOS Supported" interrupts.

Of that list we can eliminate around 11 interrupts which are not used at all (thanks in part to our disabling many external devices in BIOS before). By "not used at all" I mean that the only access to them is read-style access that is at address 0008:80401E22 where every single vector from the Vector Table is being saved, presumably before Windows switches to its own Vector Table. The only other kind of access would be the internal use by BIOS itself, both in the form of calling the interrupt and in reading off the Vector Table entry for the interrupt of the ISR itself. That allows us to exclude 11 interrupts total from the list of 19 "BIOS Supported" interrupts, which leaves us with 8 "BIOS Supported" interrupts.

Also "use" of interrupt 1E consists only of a few extra reads by Windows (to set up its own ISR), and it is not executed, so it can be eliminated as well. This lets us exclude one more interrupt.

This leaves us with 7 "BIOS Supported" interrupts which are used in some way. Those are the following interrupts:

IRQ #   Name                           # of Uniq Uses

10      Video Interface                11
11 	Equipment Check                1
13 	Fixed Disk/Diskette Interface  5
15 	System Functions Interface     8
16      Keyboard Interface             2
1A 	System Timer Interface         3
1C 	User System Timer Interrupt    0

Let's go over each of them:


3.2. BIOS32 Services

According to my tests it does not appear as if either Windows 2000 or Windows XP make any use of either "BIOS32" Service Routines.

On our system BIOS32 seems to be implemented. The magic head ("_32_") seems to be located at address 0xFD950h. This BIOS32 Service Directory Header seems in turn to point to BIOS32 Service Directory Calling Interface located at 0xFD960 (just right after the header). This Calling Interface seems to implement two functions going by the names : a) "$PCI" and b) "$BLK.".

In our memory we have implemented Plug and Play BIOS. So in theory it would seem like BIOS32 could be a convenient gateway to this as well. However, it does not seem as if BIOS32 is implementing a "$PnP" function (which would just refer to the PnP BIOS).

I also could not find what is the function with argument "$BLK". There's code for it, but it does not seem to be documented anywhere on the Internet.

More details on BIOS32 can be found in the Phoenix BIOS Manual [7] , pages 39 and 40. Another source of information is in Standard BIOS 32-bit Service Directory Proposal [15]. Here's provided local copy of the said standard proposal. .

Details: 
1)
The BIOS32 Service Directory Header
Location: 0xFD950

        _  3  2  _     : Magic ID (0x5F 0x33 0x32 0x5F)
	00 0F D9 60    : ptr to BIOS32 Service Directory Calling Interface
	00             : Version
        01             : Len of Hdr in paragraphs.; 1*paragraph=16 bytes
	94             : checksum, sums to 0x300.
 +	00 00 00 00 00 : Reserved, all set to 0.
-----------------------------------------------------
Total : 16 bytes

2)
The BIOS Service Directory Calling Interface
Location: 0xFD960

        Component Existence Function:
        Input: 
	BL  = 0;
	EAX = Component ID.
              Possible arguments : $PCI,$BLK,$PnP
	Output:
	AL  = Status
	      00 = success
	      80 = function not supported
	      81 = service does not exist
	EBX/ECX/EDX = Location/Length/Entry
3)
32-bit BIOS Service Code

BIOS32 Components:
   $PCI
        Location: F000:D9F8
	Length  :
	Entry   : 
   $BLK
        Location: F000:D992
	Length  :
	Entry   : 
   $PnP (not really bios32 function)
        Location: F000:7030
	Length  :
	Entry   : 

Summary : BIOS32 is not used by either Windows 2000 or Windows XP.


3.3. PnP BIOS Services

In regards to "PnP BIOS", it seems that Windows 2000 is making extensive use of it while in real mode, while it does not use it anymore while in protected mode. Windows XP is pretty much similar in that regard.

Documentation on the Plug and Play BIOS can be found in the Phoenix BIOS Manual [7] Pages 70 to 76.

Further "documentation" can be found at Microsoft's web site where they have Plug and Play BIOS Technology [16] web page. In there you should be able to go to "Industry Standards". There you should find two, zipped, papers titled: a) "Plug and Play BIOS Specification, Version 1.0A" and b)"Plug and Play BIOS CLARIFICATION Paper for V1.0A". Having said this, going there is not a good idea. For one thing they have this brain-dead web page which does not work with Mozilla, then you will find out that documents are in RTF (Rich Text Document) instead of PS or PDF. And once you finally convert it to readable format (OpenOffice.org [31] becomes useful here), you will find 55 pages of useless information. To save all the pain I have put local copies here, already converted into PDF format: LOCAL COPY:Plug and Play BIOS Specification, v1.0A and LOCAL COPY:Plug and Play BIOS CLARIFICATION, for v1.0A

The main point of PnP from our viewpoint would be APM. There are other services of PnP like "MultiBoot III", "SMBIOS", "PnP ISA", "Docking Station Information" etc.

On our system Plug And Play BIOS is located at 0xF7030. At that point we have a rather sizable magic header 21 bytes long.

Details: 
1)
PnP BIOS Support Installation Check
Location: 0xF7030

        $  P  n  P     : Magic ID (0x24, 0x50, 0x6E, 0x50)
	10             : Version
	21             : Length, in bytes.
	00 00          : Control Field
	04             : CheckSum (sums to 0x500h)
	00 00 00 00    : Event-notification Flag Address
	DC 5D 00 F0    : Real Mode; Entry Point; IP:CS=F000:5DDC
	04 5E          : Protected Mode; Entry Point; IP=5E04)
	00 00 0F 00    : Protected Mode; Code Segment; CS=F00
	00 00 00 00    : OEM Device Identifier
	00 F0          : Real Mode; Data Segment; DS=F000
 +	00 00 0F 00    : Protected Mode; Data Segment; DS=F00
-----------------------------------------------------
Total : 21 bytes long

Doing experiments by "erasing" the magic line "$PnP" from Shadow RAM (that is just replacing the string "24506E50" with "00000000") and starting Windows will not prevent it from running. Thus we can probably safely conclude that Plug and Play BIOS is not required in order to run Windows.


3.4. BIOS Data Areas

BIOS Implements both basic BIOS Data Area as well as Extended BIOS Data Area. The two are described below.

Our analysis seems to boil down to the fact that we probably don't have to have either of the BIOS Data Areas for MS Windows to start.


3.4.1. Basic BIOS Data Area

This is the oldest one is and is located at static location at address 400h-501h. On our system it looks as follows:

Contents of basic BIOS Data Area at 400h-501h:

000000400P 0000 0000 0000 0000 0000 0000 0000 9FC0 ................
000000410P 0022 7FFE 9102 2010 0000 001E 001E 0000 ....... ........
000000420P 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000430P 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000440P 2025 0000 0000 0000 0300 0050 1000 0000 % ........P.....
000000450P 1800 0000 0000 0000 0000 0000 0000 0000 ................
000000460P 0D0E D400 2903 8030 0002 FF09 03F1 0009 .....)0.........
000000470P 0000 0000 0100 0008 1414 1414 0101 0101 ................
000000480P 001E 003E 1018 6000 1109 000B 0058 0000 ..>....`....X...
000000490P 0000 0000 0000 1210 0000 0000 0000 0000 ................
0000004A0P 0000 0000 0000 0000 39E8 C000 0000 0000 .........9......
0000004B0P 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000004C0P 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000004D0P 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000004E0P 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000004F0P 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000500P 0000 0000 0000 0000 0000 0000 0000 0000 ................

Having it all zeroed will not prevent Windows from starting. However, we have to kick BIOS into head, since otherwise it will just loop forever inside of Interrupt 16 (keyboard). To get BIOS back on track just replace the conditional jump at F000:E2DB with two NOP's (90h's).

At offset 0xEh, we have a pointer to the Extended BIOS Data Area, currently set, in our case, to 0x9FC0h. Windows will make interrupt 15/C1 call to query for Extended Data Area (3.4.2) which would be superset of the basic BIOS Data Area. Since I would assume that that interrupt call just uses the contents of 0x0Eh, I could further speculate that the Extended BIOS Data Area is not necessary either.

I would assume it is used by Windows on the basis that Windows does test for Extended Data Area (3.4.2) which is sort of a superset of the basic Data Area.


3.4.2. Extended BIOS Data Areas (EBDA)

The Extended BIOS Data Area does not have fixed location and has to be queried via Int 15/C1.

Checking out Interrupt call 15/AH=C1, returns Carry Flag set to 1 and Register AH=86, which means "Invalid BIOS Routine Call (no EBDA)". That is sort of expected given the fact that EBDA is only for PS/2 mouse and we had disabled this in BIOS. The bottom line is that we probably don't need to implement EBDA to get Windows up.

There is a second way to find out where EBDA is by using basic BDA, and looking at offset 0xEh which should contain the address of EBDA. In 3.4.1 we have set it to 0 and it didn't prevent Windows from starting, further supporting our argument that we don't need EBDA for Windows to run.


3.5. BIOS ACPI

Advanced Configuration and Power Interface - ACPI

BIOS's/Firmware Implementation of ACPI would consist of two (three) elements:

ACPI's web site : http://www.acpi.info
Overview of ACPI : http://www.acpi.info/papers/ACPI_Overview.pdf
ACPI Specification : http://www.acpi.info/DOWNLOADS/ACPIspec-2-0a.pdf

Some information about ACPI is being returned via Int 15/AX=E820 - Query System Address Map interrupt call.

ACPI's usage by Windows, and Windows' dependency on BIOS's support of ACPI has not been investigated at the present time. However, in general just like with PNPBIOS and BIOS32, it is highly unlikely Windows would *require* ACPI in order to boot, and it is more likely a "useful", but nevertheless optional component.


4. Conclusion

Having analyzed both Windows 2000 and Windows XP, we hereby conclude that....

We have some good news. ACPI, BIOS32, PnP BIOS, basic BIOS Data Area, and Extended BIOS Data area do NOT seem to be necessary for Windows to start. And even if they are present, they can be disabled without ill effects on Windows. This leaves us with BIOS interrupts only. See section 3.1.5 For details on Interrupts.

PCI stuff is queried only via the two interrupt calls/functions below, with no BIOS32 involved

1000:00007661 CD1A        INT         1a
        AX  = B101h, PCI BIOS v2.0c+ - INSTALLATION CHECK
1000:000076DB CD1A        INT         1a
        AX = B10Eh, PCI BIOS v2.1+ - GET IRQ ROUTING INFORMATION
Interaction with APM seems to be reduced to those five interrupt calls listed below. And while PnP BIOS seems to be involved as well (PnP BIOS takes care of APM too), it can be disabled with no ill effects.
1000:0000011B CD15             INT         15
AX = 5300h, Advanced Power Management v1.0+ -INSTALLATION CHECK
1000:0000011B CD15             INT         15
AX = 5301h, Advanced Power Management v1.0+ -CONNECT REAL-MODE INTERFACE
1000:0000011B CD15             INT         15
AH = 5302h, Advanced Power Management v1.0+ -CONNECT 16-BIT PROTMODE INTERFACE
1000:0000011B CD15             INT         15
AX = 5304h, Advanced Power Management v1.0+ -DISCONNECT INTERFACE
1000:0000011B CD15             INT         15
AX = 530Eh, Advanced Power Management v1.1+ -DRIVER VERSION
Finally there's ACPI stuff which is being queried as shown below. It is not clear to what extent Windows depends on the presence of ACPI tables in order to function properly.
 2000:000004F3 CD15             INT         15
AX = E820h, Newer BIOSes - GET SYSTEM MEMORY MAP
		EDX = 534D4150h ('SMAP')
While both Basic and Extended BIOS Data Areas are used, as our experimenting has shown they are optional and thus not necessary for windows to run.

Interrupt usage for Windows 2000 and Windows XP seems very similar with XP being slightly more conservative on BIOS Interrupt usage. That would make it somewhat easier to implement, but the difference is not big.

To summarize, in order for SEBOS [20] and LinuxBIOS [18] to be able to run Windows, we would want to start our task using Windows XP, and trying to implement some subset of BIOS Interrupts. primarily the 6 (7) interrupts listed in sections 3.1.5 and 3.1.4.


5. Future work

Here I list possible issues which could be worked on in the future. Just having them listed here does not mean that any of this will actually happen. There are many *more* interesting projects than this :-)


6. Acknowledgments

We would like to thank the following people for help (in no particular order):

And everyone else whom I forgot to list above.

Also thanks go to all the people who created all those wonderful programs which helped me create this paper. This includes GNU Emacs [25], which I have used for heavy duty editing. Gnu Nano [26] which was excellent light-weight work. Dia [27]for generating flow charts. The Open Office [31] was used to generate html tables. The Gimp [28]for image processing, and W3C HTML Validation Service [29]for HTML validation.


7. References

After complaints that the above pictures in section 2.1 don't show any of the references I have used, I decided to add those two pictures. They show some of the documentation I had been using while writing this paper. It is probably something over 5'000 pages.

References - OVERVIEW References - CLOSEUP

Following references were used when writing this paper:


$Id: index2.html,v 3.33 2002/08/26 02:57:02 adam Exp adam $

Valid HTML 4.01!