# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1174071595 0
# Node ID 62754c2fdcfa923ca0efd0282e111a65ad76062b
# Parent cb1693873a7ea08cbb2e13ee9d618325b19894bb
rombios: Simplify memory-size bios calls and derive all results from
the e820 map.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
tools/firmware/rombios/rombios.c | 242 ++++++++++++---------------------------
1 files changed, 75 insertions(+), 167 deletions(-)
diff -r cb1693873a7e -r 62754c2fdcfa tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c Fri Mar 16 18:59:28 2007 +0000
+++ b/tools/firmware/rombios/rombios.c Fri Mar 16 18:59:55 2007 +0000
@@ -4196,178 +4196,86 @@ ASM_END
case 0xe8:
switch(regs.u.r8.al)
{
- case 0x20: // coded by osmaker aka K.J.
- if(regs.u.r32.edx == 0x534D4150) /* SMAP */
- {
-#ifdef HVMASSIST
- if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
- Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
-
- if (regs.u.r16.bx + 0x14 <= e820_table_size) {
- memcpyb(ES, regs.u.r16.di,
- 0xe000, 0x10 + regs.u.r16.bx, 0x14);
- }
- regs.u.r32.ebx += 0x14;
- if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- } else if (regs.u.r16.bx == 1) {
- extended_memory_size = inb_cmos(0x35);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x34);
- extended_memory_size *= 64;
- if (extended_memory_size > 0x3bc000) // greater than
EFF00000???
- {
- extended_memory_size = 0x3bc000; // everything after
this is reserved memory until we get to 0x100000000
- }
- extended_memory_size *= 1024;
- extended_memory_size += 15728640; // make up for the 16mb
of memory that is chopped off
-
- if (extended_memory_size <= 15728640)
- {
- extended_memory_size = inb_cmos(0x31);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x30);
- extended_memory_size *= 1024;
- }
-
- write_word(ES, regs.u.r16.di, 0x0000);
- write_word(ES, regs.u.r16.di+2, 0x0010);
- write_word(ES, regs.u.r16.di+4, 0x0000);
- write_word(ES, regs.u.r16.di+6, 0x0000);
-
- write_word(ES, regs.u.r16.di+8, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+10, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+12, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+14, extended_memory_size);
-
- write_word(ES, regs.u.r16.di+16, 0x1);
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- } else { /* AX=E820, DX=534D4150, BX unrecognized */
- goto int15_unimplemented;
- }
-#else
- switch(regs.u.r16.bx)
- {
- case 0:
- write_word(ES, regs.u.r16.di, 0x00);
- write_word(ES, regs.u.r16.di+2, 0x00);
- write_word(ES, regs.u.r16.di+4, 0x00);
- write_word(ES, regs.u.r16.di+6, 0x00);
-
- write_word(ES, regs.u.r16.di+8, 0xFC00);
- write_word(ES, regs.u.r16.di+10, 0x0009);
- write_word(ES, regs.u.r16.di+12, 0x0000);
- write_word(ES, regs.u.r16.di+14, 0x0000);
-
- write_word(ES, regs.u.r16.di+16, 0x1);
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 1;
-
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- case 1:
- extended_memory_size = inb_cmos(0x35);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x34);
- extended_memory_size *= 64;
- if(extended_memory_size > 0x3bc000) // greater than
EFF00000???
- {
- extended_memory_size = 0x3bc000; // everything
after this is reserved memory until we get to 0x100000000
- }
- extended_memory_size *= 1024;
- extended_memory_size += 15728640; // make up for the
16mb of memory that is chopped off
-
- if(extended_memory_size <= 15728640)
- {
- extended_memory_size = inb_cmos(0x31);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x30);
- extended_memory_size *= 1024;
- }
-
- write_word(ES, regs.u.r16.di, 0x0000);
- write_word(ES, regs.u.r16.di+2, 0x0010);
- write_word(ES, regs.u.r16.di+4, 0x0000);
- write_word(ES, regs.u.r16.di+6, 0x0000);
-
- write_word(ES, regs.u.r16.di+8, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+10, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+12, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+14, extended_memory_size);
-
- write_word(ES, regs.u.r16.di+16, 0x1);
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- default: /* AX=E820, DX=534D4150, BX unrecognized */
- goto int15_unimplemented;
+ case 0x20: {
+ Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
+
+ if (regs.u.r32.edx != 0x534D4150) /* SMAP */
+ goto int15_unimplemented;
+
+ if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
+ if (regs.u.r16.bx + 0x14 <= e820_table_size)
+ memcpyb(ES, regs.u.r16.di,
+ 0xe000, 0x10 + regs.u.r16.bx, 0x14);
+ regs.u.r32.ebx += 0x14;
+ if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
+ regs.u.r32.ebx = 0;
+ } else if (regs.u.r16.bx == 1) {
+ Bit32u base, type;
+ Bit16u off;
+ for (off = 0; off < e820_table_size; off += 0x14) {
+ base = read_dword(0xe000, 0x10 + off);
+ type = read_dword(0xe000, 0x20 + off);
+ if ((base >= 0x100000) && (type == 1))
break;
}
-#endif
- } else {
- // if DX != 0x534D4150)
- goto int15_unimplemented;
- }
+ if (off == e820_table_size) {
+ SET_CF();
+ break;
+ }
+ memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + off, 0x14);
+ regs.u.r32.ebx = 0;
+ } else { /* AX=E820, DX=534D4150, BX unrecognized */
+ goto int15_unimplemented;
+ }
+
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
break;
-
- case 0x01:
- // do we have any reason to fail here ?
- CLEAR_CF();
-
- // my real system sets ax and bx to 0
- // this is confirmed by Ralph Brown list
- // but syslinux v1.48 is known to behave
- // strangely if ax is set to 0
- // regs.u.r16.ax = 0;
- // regs.u.r16.bx = 0;
-
- // Get the amount of extended memory (above 1M)
- regs.u.r8.cl = inb_cmos(0x30);
- regs.u.r8.ch = inb_cmos(0x31);
+ }
+
+ case 0x01: {
+ Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14;
+ Bit32u base, type, size;
+
+ // do we have any reason to fail here ?
+ CLEAR_CF();
+
+ // Get the amount of extended memory (above 1M)
+ regs.u.r8.cl = inb_cmos(0x30);
+ regs.u.r8.ch = inb_cmos(0x31);
- // limit to 15M
- if(regs.u.r16.cx > 0x3c00)
- {
- regs.u.r16.cx = 0x3c00;
- }
-
- // Get the amount of extended memory above 16M in 64k blocs
- regs.u.r8.dl = inb_cmos(0x34);
- regs.u.r8.dh = inb_cmos(0x35);
-
- // Set configured memory equal to extended memory
- regs.u.r16.ax = regs.u.r16.cx;
- regs.u.r16.bx = regs.u.r16.dx;
- break;
+ // limit to 15M
+ if (regs.u.r16.cx > (15*1024))
+ regs.u.r16.cx = 15*1024;
+
+ // Find first RAM E820 entry >= 1MB.
+ for (off = 0; off < e820_table_size; off += 0x14) {
+ base = read_dword(0xe000, 0x10 + off);
+ type = read_dword(0xe000, 0x20 + off);
+ if ((base >= 0x100000) && (type == 1))
+ break;
+ }
+
+ // If there is RAM above 16MB, return amount in 64kB chunks.
+ regs.u.r16.dx = 0;
+ if (off != e820_table_size) {
+ size = base + read_dword(0xe000, 0x18 + off);
+ if (size > 0x1000000) {
+ size -= 0x1000000;
+ regs.u.r16.dx = (Bit16u)(size >> 16);
+ }
+ }
+
+ // Set configured memory equal to extended memory
+ regs.u.r16.ax = regs.u.r16.cx;
+ regs.u.r16.bx = regs.u.r16.dx;
+ break;
+ }
default: /* AH=0xE8?? but not implemented */
- goto int15_unimplemented;
- }
- break;
+ goto int15_unimplemented;
+ }
+ break;
int15_unimplemented:
// fall into the default
default:
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|