Updated notes

This commit is contained in:
Jeff Parsons 2015-04-18 11:05:12 -07:00 committed by jeffpar
commit ef63a126f5
2 changed files with 92 additions and 34 deletions

View file

@ -2,43 +2,95 @@ Compaq DeskPro 386 Update
---
PCjs can now boot the [Compaq DeskPro 386/16 ROM BIOS](/devices/pc/bios/compaq/deskpro386/).
There's still a problem with the hard disk controller, which I haven't looked into yet, but
it can be bypassed. Booting from a floppy works.
There's still a problem with the hard disk controller, which I haven't looked into yet,
but booting from a floppy works.
While working through issues with this ROM BIOS, I created some lightly-annotated
[source code](/devices/pc/bios/compaq/deskpro386/1988-01-28.nasm) that can be re-assembled
with [NASM](http://www.nasm.us/). The process of creating the initial source code is
with [NASM](http://www.nasm.us/). The initial process of creating the source code is
explained [here](/devices/pc/bios/compaq/deskpro386/#producing-rom-source-code).
During the debugging process, I also came across a real head-scratcher. Take a look at this code
at F000:BCAF:
At the top of the source code, I explain a few important details about ROM addresses that
are worth recapping here:
> This 32Kb ROM image is ORG'ed at 0x8000, because most of its code is designed to run
at real-mode addresses F000:8000 through F000:FFFF.
> And even though the 80386 resets with CS:IP set to F000:FFF0, the physical base address
of CS is set to %FFFF0000, which means the ROM must also be mapped at physical addresses
%FFFF8000 through %FFFFFFFF.
> Additionally, DeskPro 386 systems mirror this 32Kb ROM at real-mode address F000:0000
through F000:7FFF. Once again, that region is mirrored at physical addresses %FFFF0000
through %FFFF7FFFF.
> In other words, both 32Kb halves of the last 64Kb of both the first and last megabyte
of the 80386's 32Gb address space are physically mapped to this ROM image.
> Finally, the DeskPro 386 has a "RAM Relocation" feature that allows 128Kb of RAM at
%00FE0000 through %00FFFFFF to be mapped to %000E0000 through %000FFFFF, effectively
replacing the ROM in the first megabyte with write-protected RAM; the top 64Kb of that
RAM must first be initialized with the 64Kb at %000F0000 prior to remapping. It's also
possible to copy external ROMs from %000C0000 through %000EFFFF into the bottom 64Kb of
that RAM, but this is only done for ROMs known to contain relocatable code (eg, a Compaq
Enhanced Video Graphics card).
> Every DeskPro 386 system must have a MINIMUM of 1Mb of RAM, of which either 256Kb,
512Kb, or 640Kb can be physically mapped as conventional memory (at the bottom of the
first megabyte), with the remainder (either 768Kb, 512Kb, or 384Kb) physically mapped
to the top of the 16th megabyte (ending at address %00FFFFFF), the last 128Kb of which
is used by the "RAM Relocation" feature. The remaining memory immediately below that
128Kb (ie, below %00FE0000) can only be accessed by special system software, such as CEMM.
> Compaq refers to that remaining memory as "Compaq Built-in Memory".
So there you have it. Once the ROM has relocated itself to RAM at the top of the 16th
megabyte, there are no less than THREE physical address ranges where ROM code and data
structures can be accessed:
1. %000F0000 through %000FFFFF (aka real-mode adresses F000:0000 through F000:FFFF)
2. %00FF0000 through %00FFFFFF (the relocated copy)
3. %FFFF0000 through %FFFFFFFF (the physical alias of %000F0000 through %000FFFFF)
As you would expect, most of the ROM's code and data references are to first megabyte,
since most of the code is designed to run in real-mode. But there are portions that
run in protected-mode, and those portions are much less consistent about which address
range to use -- no doubt, in part, because it makes no difference. The ROM does
not run with paging enabled, so any physical address is as easy to access as any other.
Unless, of course, the A20 line is disabled. In that case, only the first range is
accessible; the other two are not.
And unfortunately, I've come across a code path in the ROM that attempts to switch to
protected-mode while the A20 line is still disabled, with the GDTR pointing to memory
that requires A20. The result is an immediate crash. Here's the code:
;;
;; Relocate the ROM and initialize conventional RAM
;; Switch to protected-mode, relocate the ROM, switch back to real-mode, disable
;; the A20 line, and then initialize all conventional RAM.
;;
call xc825 ; 0000BCAF E8730B
;;
;; This function loads the GDTR with [00FF0730,0047], but since the previous call
;; The next function loads the GDTR with [00FF0730,0047], but since the previous call
;; disabled the A20 line, the first selector load crashes, because physical address
;; %FF0730 requires A20.
;;
call xf480 ; 0000BCB2 E8CB37
The first call (to F000:C825) is to a long, fairly linear function that includes a call to F000:A478,
a small function whose sole purpose is to issue an 8042 Keyboard Controller command that disables the A20
line.
The code at C825 is a long, fairly linear function that includes a call to A478, a small
function whose sole purpose is to issue an 8042 Keyboard Controller command that disables
the A20 line.
;;
;; Disable A20
;;
call xa478 ; 0000C8B4 E8C1DB
After disabling A20, the function at F000:C825 then performs a series of `rep stosd` to zero all
conventional (below 1Mb) RAM, and then it returns to the code at F000:BCB2, which in turn calls F000:F480.
After disabling A20, the code at C825 then performs a series of `rep stosd` to zero all
conventional (below 1Mb) RAM, and then it returns to BCB2, which in turn calls F480.
Here's the problem: the code at F000:F480 almost immediately attempts to enter protected-mode, which
fails because A20 is disabled.
The code at F480 almost immediately attempts to enter protected-mode:
;;
;; When we arrive here, the A20 line has been disabled, so in theory, the GDT is
@ -58,10 +110,10 @@ fails because A20 is disabled.
mov cr0,eax ; 0000F4A4 0F2200
jmp 0x28:xf4ac ; 0000F4A7 EAACF42800
I don't see how the above code can work. The JMP instruction will invariably fault, because the
GDTR is pointing to memory that cannot be accessed when A20 is disabled.
The JMP instruction will invariably fault, because the GDT is located in memory that cannot be
accessed when A20 is disabled.
The code at F000:F498 is not called from any other place. It can only be reached by running the
The code at F498 is not called from any other place. It can only be reached by running the
preceding code which, among other things, disables A20. And there's only one branch between that
code and the code that enters protected-mode that could possibly make any difference:

View file

@ -9,29 +9,34 @@
;
; Overview
; --------
; This 32Kb ROM image is ORG'ed at 0x8000, because it needs to run at real-mode
; addresses F000:8000 through F000:FFFF, as well as protected-mode physical addresses
; %FFFF8000 through %FFFFFFFF. Additionally, DeskPro 386 systems mirror this 32Kb ROM
; at real-mode addresses F000:0000 through F000:7FFF, as well as protected-mode physical
; addresses %FFFF0000 through %FFFF7FFF.
; This 32Kb ROM image is ORG'ed at 0x8000, because most of its code is designed to run
; at real-mode addresses F000:8000 through F000:FFFF.
;
; In other words, both 32Kb halves of the top 64Kb of both the first megabyte and the
; 16th megabyte are physically mapped to this ROM image.
; And even though the 80386 resets with CS:IP set to F000:FFF0, the physical base address
; of CS is set to %FFFF0000, which means the ROM must also be mapped at physical addresses
; %FFFF8000 through %FFFFFFFF.
;
; Additionally, DeskPro 386 systems mirror this 32Kb ROM at real-mode address F000:0000
; through F000:7FFF. And that region is similarly mirrored at physical addresses %FFFF0000
; through %FFFF7FFFF.
;
; In other words, both 32Kb halves of the last 64Kb of both the first and last megabyte
; of the 80386's 32Gb address space are physically mapped to this ROM image.
;
; Finally, the DeskPro 386 has a "RAM Relocation" feature that allows 128Kb of RAM at
; %FE0000 through %FFFFFF to be mapped to %0E0000 through %0FFFFF, effectively replacing
; the ROM in the first megabyte with write-protected RAM; the top 64Kb of that RAM must
; first be initialized with the 64Kb at %0F0000 prior to remapping. It's also possible
; to copy external ROMs from %0C0000 through %0EFFFF into the bottom 64Kb of that RAM,
; but this is only done for ROMs known to contain relocatable code (eg, a Compaq Enhanced
; Video Graphics card).
; %00FE0000 through %00FFFFFF to be mapped to %000E0000 through %000FFFFF, effectively
; replacing the ROM in the first megabyte with write-protected RAM; the top 64Kb of that
; RAM must first be initialized with the 64Kb at %000F0000 prior to remapping. It's also
; possible to copy external ROMs from %000C0000 through %000EFFFF into the bottom 64Kb of
; that RAM, but this is only done for ROMs known to contain relocatable code (eg, a Compaq
; Enhanced Video Graphics card).
;
; Every DeskPro 386 system must have a MINIMUM of 1Mb of RAM, of which either 256Kb,
; 512Kb, or 640Kb can be physically mapped as conventional memory (at the bottom of the
; first megabyte), with the remainder (either 768Kb, 512Kb, or 384Kb) physically mapped
; to the top of the 16th megabyte (ending at address %FFFFFF), the last 128Kb of which
; to the top of the 16th megabyte (ending at address %00FFFFFF), the last 128Kb of which
; is used by the "RAM Relocation" feature. The remaining memory immediately below that
; 128Kb (ie, below %FE0000) can only be accessed by special system software, such as CEMM.
; 128Kb (ie, below %00FE0000) can only be accessed by special system software, such as CEMM.
;
; Compaq refers to that remaining memory as "Compaq Built-in Memory".
;
@ -6626,12 +6631,13 @@ xbc71: call xa3e0 ; 0000BC71 E86CE7 '.l.'
call xd6dd ; 0000BCAC E82E1A '...'
;;
;; Relocate the ROM and initialize conventional RAM
;; Switch to protected-mode, relocate the ROM, switch back to real-mode, disable
;; the A20 line, and then initialize all conventional RAM.
;;
call xc825 ; 0000BCAF E8730B
;;
;; This function loads the GDTR with [00FF0730,0047], but since the previous call
;; The next function loads the GDTR with [00FF0730,0047], but since the previous call
;; disabled the A20 line, the first selector load crashes, because physical address
;; %FF0730 requires A20.
;;