hello, can anyone point me to an documenation on bios's interrupt 15, ah=87. It is 'copy extended memory'.
I suspect the implementation I have is wrong, and thus stops me from adding support for legacy applications under LinuxBIOS.
Going over phoenix manual and Ralf Browns's interrupt list, I know that
CX = counter ES:SI = pointer to GDT
what is not clear to me is what does determine source and destination of the copy. Would it just copy between first and second segment (if so why it is not documented).
Adam Sulmicki adam@cfar.umd.edu writes:
hello, can anyone point me to an documenation on bios's interrupt 15, ah=87. It is 'copy extended memory'.
I suspect the implementation I have is wrong, and thus stops me from adding support for legacy applications under LinuxBIOS.
Going over phoenix manual and Ralf Browns's interrupt list, I know that
CX = counter ES:SI = pointer to GDT
what is not clear to me is what does determine source and destination of the copy. Would it just copy between first and second segment (if so why it is not documented).
I have in my documentation the following addtional information. CX is a count of works (2 byte quantities) With the max being 0x8000
And the format of the GDT is: dummy GDT location source GDT entry target GDT entry BIOS CS BIOS SS
This code works for a 286 so it has a 16MB limit. And segments are limted to 64K, if my memory serves me correctly.
Eric
FWIW, here's summary what I was able to gather so far
And the format of the GDT is: dummy GDT location source GDT entry target GDT entry BIOS CS BIOS SS
ok, I think I got it nailed down, how about the way it is below?
I'm not quite sure of your interpretation of #2 (GDT location), can you elaborate? Ie what would it be used for by BIOS. It seems to me like I already get this info from ES:SI.
CX = counter of 2-byte words ES:SI = pointer to to a structure of size of 0x30 which contains 6 GDT entries.
1 0x00 Reserved GDT (all 0's) 2 0x08 FS & GS GDT 3 0x10 DS (src) GDT 4 0x18 ES (dst) GDT 5 0x20 CS (bios) GDT 6 0x28 SS (bios) GDT
of all those caller of the interrupt is required to only fill out #3 and #4 and leave all other blank.
Because we are not passed indirect link with (size of GDT,ptr to GDT) we can't use it directly in our LGDT call (after filling out missing info). We have to either copy it over or add another level of indirection.
Adam Sulmicki adam@cfar.umd.edu writes:
FWIW, here's summary what I was able to gather so far
And the format of the GDT is: dummy GDT location source GDT entry target GDT entry BIOS CS BIOS SS
ok, I think I got it nailed down, how about the way it is below?
I'm not quite sure of your interpretation of #2 (GDT location), can you elaborate? Ie what would it be used for by BIOS. It seems to me like I already get this info from ES:SI.
CX = counter of 2-byte words ES:SI = pointer to to a structure of size of 0x30 which contains 6 GDT entries.
1 0x00 Reserved GDT (all 0's) 2 0x08 FS & GS GDT
(I think this is actually for the indirect link)
3 0x10 DS (src) GDT 4 0x18 ES (dst) GDT 5 0x20 CS (bios) GDT 6 0x28 SS (bios) GDT
of all those caller of the interrupt is required to only fill out #3 and #4 and leave all other blank.
Because we are not passed indirect link with (size of GDT,ptr to GDT) we can't use it directly in our LGDT call (after filling out missing info). We have to either copy it over or add another level of indirection.
I would put the indirect link in table entry 0x00. That way you can trivially call lgdt with the address of the gdt... Table entry 0x01 would do as well, and I think that is what my documentation was suggesting.
Eric
On Sat, Oct 26, 2002 at 08:32:48AM -0400, Adam Sulmicki wrote:
hello, can anyone point me to an documenation on bios's interrupt 15, ah=87. It is 'copy extended memory'.
This is such a bitch. I simply could not get this to work and I didn't have proper tools to debug what was going on. Here's what RB says anyway:
--------B-1587------------------------------- INT 15 - SYSTEM - COPY EXTENDED MEMORY AH = 87h CX = number of words to copy (max 8000h) ES:SI -> global descriptor table (see #0393) Return: CF set on error CF clear if successful AH = status (see #0392) Notes: copy is done in protected mode with interrupts disabled by the default BIOS handler; many 386 memory managers perform the copy with interrupts enabled this function is incompatible with the OS/2 compatibility box SeeAlso: AH=88h,AH=89h,INT 1F/AH=90h
(Table 0392) Values for extended-memory copy status: 00h source copied into destination 01h parity error 02h interrupt error 03h address line 20 gating failed 80h invalid command (PC,PCjr) 86h unsupported function (XT,PS30)
Format of global descriptor table: Offset Size Description (Table 0393) 00h 16 BYTEs zeros (used by BIOS) 10h WORD source segment length in bytes (2*CX-1 or greater) 12h 3 BYTEs 24-bit linear source address, low byte first 15h BYTE source segment access rights (93h) 16h WORD zero 18h WORD destination segment length in bytes (2*CX-1 or greater) 1Ah 3 BYTEs 24-bit linear destination address, low byte first 1Dh BYTE destination segment access rights (93h) 1Eh 18 BYTEs zeros (used by BIOS)
It should all be pretty straight forward. The 16 bytes at 00h and the 18 bytes at 1Eh are probably best used by BIOS to set up it's own segments for usage during the copy. And don't forget the 32-bit opcodes when in pmode.
//Peter
This is such a bitch.
yeah.
I simply could not get this to work
you can find nice example how to use it in linux sources (some file in linux/arch/i386/boot, head.S IIRC)
Here's what RB says anyway:
[snip]
It should all be pretty straight forward. The 16 bytes at 00h and the 18 bytes at 1Eh are probably best used by BIOS to set up it's own segments for usage during the copy.
yeah, but I hoped for more authoritative answer than DB.
For example the description in Phoenix's user manual is just plain wrong :/ It will describe an single GDT entry, but it will not say how many entries and what is meaning of each entry.
http://www.phoenix.com/resources/userman.pdf
And don't forget the 32-bit opcodes when in pmode.
Isn't that dependent on D/B flag in appropriate GDT entry? So if I set 16 b it D/B flag in the CS entry, I still should be able to use 16 bit code, even if in 32 bit mode.
On Sun, Oct 27, 2002 at 07:05:58PM -0500, Adam Sulmicki wrote:
you can find nice example how to use it in linux sources (some file in linux/arch/i386/boot, head.S IIRC)
Using it is the easy part, I had to implement it. Fortunately that project got dropped before I tore all my hair off. :)
For example the description in Phoenix's user manual is just plain wrong :/ It will describe an single GDT entry, but it will not say how many entries and what is meaning of each entry.
Some resource, huh? Good thing we have RB.
And don't forget the 32-bit opcodes when in pmode.
Isn't that dependent on D/B flag in appropriate GDT entry? So if I set 16 b it D/B flag in the CS entry, I still should be able to use 16 bit code, even if in 32 bit mode.
Yes! This is, of course, absolutely correct. I just wasn't familiar enough with the descriptor flags. Now I actually know enough to make my own DOS extender. :) (Well, probably not, but a little closer.)
I haven't found a complete descriptor description so I'll post an attempt here. It's basically just different parts of 386intel.txt put together. (That file sure isn't very well structured. Much like the architecture itself I guess. :)
DESC STRUC lim_0_15 DW 0 ; limit bits (0..15) bas_0_15 DW 0 ; base bits (0..15) bas_16_23 DB 0 ; base bits (16..23) access DB 0 ; access byte ; access := P DPL RES1 TYPE [A] ; P:1 Segment present (eg. for swapping to disk) ; DPL:2 Descriptor Privilege Level ; RES1:1 Means this is an application (as opposed to system) segment #if RES1.value ; TYPE:3 Indicates what kind of segment this is and the intended use ; A:1 Accessed bit, set by CPU when the segment is used #else ; TYPE:4 Indicates what kind of segment this is and the intended use #endif gran DB 0 ; granularity byte ; gran := G (B|D|X) O AVL lim_16_19 ; G:1 0=>byte granularity, 1=>page(4k) granularity #if RES1.value #if IS_DATA_SEGMENT ; B:1 Big segment (affects segment bounds) #else ; D:1 Default, determines default operand-size for code segments #endif /* IS_DATA_SEGMENT */ #else ; X:1 unknown, unused? #endif /* RES1.value */ ; O:1 unknown, used for protection? ; AVL:1 Available for use by systems programmers ; lim_16_19:4 limit bits (16..19) bas_24_31 DB 0 ; base bits (24..31) DESC ENDS
//Peter