On Wednesday, June 23, Daniel Dickman wrote:
>
> Index: amd64/stand/libsa/memprobe.c
> ===================================================================
> RCS file: /usr/cvs/src/sys/arch/amd64/stand/libsa/memprobe.c,v
> retrieving revision 1.6
> diff -u -r1.6 memprobe.c
> --- amd64/stand/libsa/memprobe.c 30 Nov 2009 16:33:20 -0000 1.6
> +++ amd64/stand/libsa/memprobe.c 24 Jun 2010 00:04:47 -0000
> @@ -72,9 +72,9 @@
> do {
> BIOS_regs.biosr_es = ((u_int)(mp) >> 4);
> __asm __volatile(DOINT(0x15) "; setc %b1"
> - : "=a" (sig), "=d" (rc), "=b" (off)
> - : "0" (0xE820), "1" (0x534d4150), "b" (off),
> - "c" (sizeof(*mp)), "D" (((u_int)mp) & 0xF)
> + : "=a" (sig), "=c" (rc), "=b" (off)
> + : "0" (0xE820), "d" (0x534d4150), "b" (off),
> + "1" (sizeof(*mp)), "D" (((u_int)mp) & 0xF)
> : "cc", "memory");
> off = BIOS_regs.biosr_bx;
If you notice, the asm part does a "setc %b1". And in your
case, that would simply nuke %ecx. The original code did not
take into account the length returned, it ignored it as it
was asking for the max, some biosen always return the max,
and nothing should ever return more than what was asked for,
or less than 20 bytes.
I don't know how this fixes any bug off hand. The following
diff may. Compiled tested, but otherwise not tested. Similar
diff would need to be made for i386:
Index: memprobe.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/stand/libsa/memprobe.c,v
retrieving revision 1.46
diff -u memprobe.c
--- memprobe.c 30 Nov 2009 16:33:20 -0000 1.46
+++ memprobe.c 24 Jun 2010 03:45:11 -0000
@@ -67,19 +67,19 @@
static __inline bios_memmap_t *
bios_E820(bios_memmap_t *mp)
{
- int rc, off = 0, sig, gotcha = 0;
+ int rc, off = 0, sig, gotcha = 0, size = 0;
do {
BIOS_regs.biosr_es = ((u_int)(mp) >> 4);
__asm __volatile(DOINT(0x15) "; setc %b1"
- : "=a" (sig), "=d" (rc), "=b" (off)
+ : "=a" (sig), "=d" (rc), "=b" (off), "=c" (size)
: "0" (0xE820), "1" (0x534d4150), "b" (off),
- "c" (sizeof(*mp)), "D" (((u_int)mp) & 0xF)
+ "3" (sizeof(*mp)), "D" (((u_int)mp) & 0xF)
: "cc", "memory");
off = BIOS_regs.biosr_bx;
- if (rc & 0xff || sig != 0x534d4150)
+ if (rc & 0xff || sig != 0x534d4150 || size != 20)
break;
gotcha++;
if (!mp->type)
Chances are the diff will need to be applied by hand (just noticed
the space/tab isue with it).
--Toby.