diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-10-10 12:10:24 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-13 12:26:58 -0700 |
commit | 652c3057145a41703e5e817d86b2584db9ab806d (patch) | |
tree | 003b164e76dad49fe944c2053dad89208e93f7e2 /memdisk | |
parent | ef45d17e31d591a579c1d51a5e6a026493465a64 (diff) | |
download | syslinux-652c3057145a41703e5e817d86b2584db9ab806d.tar.gz |
Support "extended attributes" for INT 15h, AX=E820h
Some blithering idiot thought it was a good idea to introduce
"extended attributes" for INT 15h, AX=E820h, and in doing so, breaking
compatibility with ALL E820 users out there. F*cking morons.
Implement handling of extended attributes in:
- e820 parsing in the core
- e820 parsing in libcom32
- e820 parsing *and proxying* in memdisk
The latter is the really painful one.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'memdisk')
-rw-r--r-- | memdisk/e820.h | 3 | ||||
-rw-r--r-- | memdisk/e820data | 26 | ||||
-rw-r--r-- | memdisk/e820func.c | 42 | ||||
-rw-r--r-- | memdisk/e820test.c | 15 | ||||
-rw-r--r-- | memdisk/memdisk.asm | 30 | ||||
-rw-r--r-- | memdisk/msetup.c | 21 | ||||
-rw-r--r-- | memdisk/setup.c | 4 |
7 files changed, 87 insertions, 54 deletions
diff --git a/memdisk/e820.h b/memdisk/e820.h index 04b44484..429b98c2 100644 --- a/memdisk/e820.h +++ b/memdisk/e820.h @@ -21,6 +21,7 @@ struct e820range { uint64_t start; uint32_t type; + uint32_t extattr; } __attribute__((packed)); extern struct e820range ranges[]; @@ -28,6 +29,6 @@ extern int nranges; extern uint32_t dos_mem, low_mem, high_mem; extern void e820map_init(void); -extern void insertrange(uint64_t, uint64_t, uint32_t); +extern void insertrange(uint64_t, uint64_t, uint32_t, uint32_t); extern void get_mem(void); extern void parse_mem(void); diff --git a/memdisk/e820data b/memdisk/e820data index 34ab566d..14320aac 100644 --- a/memdisk/e820data +++ b/memdisk/e820data @@ -1,13 +1,15 @@ -0000000000000000 000000000009bc00 1 -000000000009bc00 0000000000004400 2 -00000000000e9800 0000000000016800 2 -0000000000100000 0000000006ee0000 1 -0000000006fe0000 000000000000fc00 3 -0000000006fefc00 0000000000000400 4 -0000000006ff0000 0000000000002000 2 -0000000006ff2000 000000000000e000 1 -0000000007000000 0000000000100000 2 -00000000fff00000 0000000000100000 2 +0000000000000000 000000000009bc00 1 1 +000000000009bc00 0000000000004400 2 1 +00000000000e9800 0000000000016800 2 1 +00000000000e9800 000000000000b400 2 1 +00000000000f5000 000000000000b000 2 9 +0000000000100000 0000000006ee0000 1 1 +0000000006fe0000 000000000000fc00 3 1 +0000000006fefc00 0000000000000400 4 1 +0000000006ff0000 0000000000002000 2 1 +0000000006ff2000 000000000000e000 1 1 +0000000007000000 0000000000100000 2 1 +00000000fff00000 0000000000100000 2 1 -0000000000586000 0000000000168000 2 -000000000009ba00 0000000000000200 2 +0000000000586000 0000000000168000 2 1 +000000000009ba00 0000000000000200 2 1 diff --git a/memdisk/e820func.c b/memdisk/e820func.c index 577469b7..a6896745 100644 --- a/memdisk/e820func.c +++ b/memdisk/e820func.c @@ -17,7 +17,11 @@ */ #include <stdint.h> +#ifdef TEST +#include <string.h> +#else #include "memdisk.h" /* For memset() */ +#endif #include "e820.h" #define MAXRANGES 1024 @@ -33,25 +37,28 @@ void e820map_init(void) ranges[1].type = -1; } -static void insertrange_at(int where, uint64_t start, uint32_t type) +static void insertrange_at(int where, uint64_t start, + uint32_t type, uint32_t extattr) { int i; for ( i = nranges ; i > where ; i-- ) ranges[i] = ranges[i-1]; - ranges[where].start = start; - ranges[where].type = type; + ranges[where].start = start; + ranges[where].type = type; + ranges[where].extattr = extattr; nranges++; - ranges[nranges].start = 0ULL; - ranges[nranges].type = (uint32_t)-1; + ranges[nranges].start = 0ULL; + ranges[nranges].type = (uint32_t)-1; + ranges[nranges].extattr = 0; } -void insertrange(uint64_t start, uint64_t len, uint32_t type) +void insertrange(uint64_t start, uint64_t len, uint32_t type, uint32_t extattr) { uint64_t last; - uint32_t oldtype; + uint32_t oldtype, oldattr; int i, j; /* Remove this to make len == 0 mean all of memory */ @@ -61,35 +68,42 @@ void insertrange(uint64_t start, uint64_t len, uint32_t type) last = start+len-1; /* May roll over */ i = 0; - oldtype = -2; - while ( start > ranges[i].start && ranges[i].type != -1 ) { + oldtype = -2U; + oldattr = 0; + while ( start > ranges[i].start && ranges[i].type != -1U ) { oldtype = ranges[i].type; + oldattr = ranges[i].extattr; i++; } /* Consider the replacement policy. This current one is "overwrite." */ - if ( start < ranges[i].start || ranges[i].type == -1 ) - insertrange_at(i++, start, type); + if ( start < ranges[i].start || ranges[i].type == -1U ) + insertrange_at(i++, start, type, extattr); while ( i == 0 || last > ranges[i].start-1 ) { oldtype = ranges[i].type; - ranges[i].type = type; + oldattr = ranges[i].extattr; + ranges[i].type = type; + ranges[i].extattr = extattr; i++; } if ( last < ranges[i].start-1 ) - insertrange_at(i, last+1, oldtype); + insertrange_at(i, last+1, oldtype, oldattr); /* Now the map is correct, but quite possibly not optimal. Scan the map for ranges which are redundant and remove them. */ i = j = 1; oldtype = ranges[0].type; + oldattr = ranges[0].extattr; while ( i < nranges ) { - if ( ranges[i].type == oldtype ) { + if ( ranges[i].type == oldtype && + ranges[i].extattr == oldattr ) { i++; } else { oldtype = ranges[i].type; + oldattr = ranges[i].extattr; if ( i != j ) ranges[j] = ranges[i]; i++; j++; diff --git a/memdisk/e820test.c b/memdisk/e820test.c index c2be7437..41fee007 100644 --- a/memdisk/e820test.c +++ b/memdisk/e820test.c @@ -36,17 +36,17 @@ void printranges(void) { int i; for ( i = 0 ; i < nranges ; i++ ) { - printf("%016llx %016llx %d\n", + printf("%016llx %016llx %d %x\n", ranges[i].start, ranges[i+1].start - ranges[i].start, - ranges[i].type); + ranges[i].type, ranges[i].extattr); } } int main(void) { uint64_t start, len; - uint32_t type; + uint32_t type, extattr; char line[BUFSIZ], *p; e820map_init(); @@ -55,11 +55,12 @@ int main(void) while ( fgets(line, BUFSIZ, stdin) ) { p = strchr(line, ':'); p = p ? p+1 : line; - if ( sscanf(p, " %llx %llx %d", &start, &len, &type) == 3 ) { + extattr = 1; + if ( sscanf(p, " %llx %llx %d %x", &start, &len, &type, &extattr) >= 3 ) { putchar('\n'); - printf("%016llx %016llx %d <-\n", start, len, type); + printf("%016llx %016llx %d %x <-\n", start, len, type, extattr); putchar('\n'); - insertrange(start, len, type); + insertrange(start, len, type, extattr); printranges(); } } @@ -73,7 +74,7 @@ int main(void) putchar('\n'); /* Now, steal a chunk (2K) of DOS memory and make sure it registered OK */ - insertrange(dos_mem-2048, 2048, 2); /* Type 2 = reserved */ + insertrange(dos_mem-2048, 2048, 2, 1); /* Type 2 = reserved */ printranges(); parse_mem(); diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm index eb4370ab..47b55fce 100644 --- a/memdisk/memdisk.asm +++ b/memdisk/memdisk.asm @@ -530,38 +530,46 @@ EDDEject: ; int15_e820: cmp edx,534D4150h ; "SMAP" - jne near oldint15 + jne oldint15 cmp ecx,20 ; Need 20 bytes jb err86 push ds push cs pop ds + push edx ; "SMAP" and ebx,ebx jne .renew mov ebx,E820Table .renew: - add bx,12 ; Advance to next - mov eax,[bx-4] ; Type + add bx,16 ; Advance to next + mov eax,[bx-8] ; Type and eax,eax ; Null type? jz .renew ; If so advance to next mov [es:di+16],eax - mov eax,[bx-12] ; Start addr (low) + and cl,~3 + cmp ecx,24 + jb .no_extattr + mov eax,[bx-4] ; Extended attributes + mov [es:di+20],eax + mov ecx,24 ; Bytes loaded +.no_extattr: + push ecx + mov eax,[bx-16] ; Start addr (low) mov [es:di],eax - mov ecx,[bx-8] ; Start addr (high) - mov [es:di+4],ecx + mov ecx,[bx-12] ; Start addr (high) + mov [es:di+4],edx mov eax,[bx] ; End addr (low) - mov ecx,[bx+4] ; End addr (high) - sub eax,[bx-12] ; Derive the length - sbb ecx,[bx-8] + mov edx,[bx+4] ; End addr (high) + sub eax,[bx-16] ; Derive the length + sbb edx,[bx-12] mov [es:di+8],eax ; Length (low) mov [es:di+12],ecx ; Length (high) cmp dword [bx+8],-1 ; Type of next = end? jne .notdone xor ebx,ebx ; Done with table .notdone: - mov eax,edx ; "SMAP" + pop eax ; "SMAP" pop ds - mov ecx,20 ; Bytes loaded int15_success: mov byte [bp+6], 02h ; Clear CF pop bp diff --git a/memdisk/msetup.c b/memdisk/msetup.c index 12ba2179..f126d878 100644 --- a/memdisk/msetup.c +++ b/memdisk/msetup.c @@ -27,6 +27,7 @@ static inline int get_e820(void) uint64_t base; uint64_t len; uint32_t type; + uint32_t extattr; } *buf = sys_bounce; uint32_t copied; int range_count = 0; @@ -47,12 +48,18 @@ static inline int get_e820(void) if ( regs.eax.l != 0x534d4150 || copied < 20 ) break; - printf("e820: %08x%08x %08x%08x %d\n", + if ( copied < 24 ) + buf->extattr = 1; + + printf("e820: %08x%08x %08x%08x %d [%x]\n", (uint32_t)(buf->base >> 32), (uint32_t)buf->base, (uint32_t)(buf->len >> 32), (uint32_t)buf->len, - buf->type); + buf->type, buf->extattr); + + if ( !(buf->extattr & 1) ) + continue; /* Disabled range, just ignore */ - insertrange(buf->base, buf->len, buf->type); + insertrange(buf->base, buf->len, buf->type, buf->extattr); range_count++; } while ( regs.ebx.l ); @@ -66,7 +73,7 @@ static inline void get_dos_mem(void) memset(®s, 0, sizeof regs); syscall(0x12, ®s, ®s); - insertrange(0, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1); + insertrange(0, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1, 1); printf(" DOS: %d K\n", regs.eax.w[0]); } @@ -82,10 +89,10 @@ static inline int get_e801(void) if ( !(err = regs.eflags.l & 1) ) { if ( regs.eax.w[0] ) { - insertrange(0x100000, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1); + insertrange(0x100000, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1, 1); } if ( regs.ebx.w[0] ) { - insertrange(0x1000000, (uint64_t)((uint32_t)regs.ebx.w[0] << 16), 1); + insertrange(0x1000000, (uint64_t)((uint32_t)regs.ebx.w[0] << 16), 1, 1); } printf("e801: %04x %04x\n", regs.eax.w[0], regs.ebx.w[0]); @@ -107,7 +114,7 @@ static inline int get_88(void) if ( !(err = regs.eflags.l & 1) ) { if ( regs.eax.w[0] ) { - insertrange(0x100000, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1); + insertrange(0x100000, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1, 1); } printf(" 88: %04x\n", regs.eax.w[0]); diff --git a/memdisk/setup.c b/memdisk/setup.c index 583570ea..a52f136c 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -654,7 +654,7 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce) do_edd ? "on" : "off"); /* Reserve the ramdisk memory */ - insertrange(ramdisk_image, ramdisk_size, 2); + insertrange(ramdisk_image, ramdisk_size, 2, 1); parse_mem(); /* Recompute variables */ /* Figure out where it needs to go */ @@ -772,7 +772,7 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce) /* Reserve this range of memory */ wrz_16(BIOS_BASEMEM, driveraddr >> 10); - insertrange(driveraddr, dos_mem-driveraddr, 2); + insertrange(driveraddr, dos_mem-driveraddr, 2, 1); parse_mem(); pptr->mem1mb = low_mem >> 10; |