[syslinux] [RFC][PATCH] fsc: convert the highmem.inc from assembly to C code
Feng Tang
feng.tang at intel.com
Fri Dec 18 05:44:57 PST 2009
All,
Here is a RFC patch for converting the highmem.inc to C code, which doesn't
touch the core part. please help to review, thanks
Thanks,
Feng
From 18ed969a36be6331eaec115fda7680a773ec84fd Mon Sep 17 00:00:00 2001
From: Feng Tang <feng.tang at intel.com>
Date: Fri, 18 Dec 2009 15:11:19 +0800
Subject: [PATCH] fsc: convert the highmem.inc from assembly to C code
Signed-off-by: Feng Tang <feng.tang at intel.com>
---
core/common.inc | 2 +-
core/configinit.inc | 2 +-
core/extern.inc | 3 +
core/highmem.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++
core/highmem.inc | 158 --------------------------------------------------
5 files changed, 164 insertions(+), 160 deletions(-)
create mode 100644 core/highmem.c
delete mode 100644 core/highmem.inc
diff --git a/core/common.inc b/core/common.inc
index 7078011..422f1c9 100644
--- a/core/common.inc
+++ b/core/common.inc
@@ -14,7 +14,7 @@
%include "loadhigh.inc" ; Load a file into high memory
%include "font.inc" ; VGA font stuff
%include "graphics.inc" ; VGA graphics
-%include "highmem.inc" ; High memory sizing
+;%include "highmem.inc" ; High memory sizing
%include "strcpy.inc" ; strcpy()
%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
diff --git a/core/configinit.inc b/core/configinit.inc
index 1dd253c..dc09139 100644
--- a/core/configinit.inc
+++ b/core/configinit.inc
@@ -19,7 +19,7 @@
section .text16
reset_config:
- call highmemsize
+ pm_call highmem_init
; Initialize the .config section
xor eax,eax
diff --git a/core/extern.inc b/core/extern.inc
index 95a9c88..b1f6a7f 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -12,6 +12,9 @@
; hello.c
extern hello
+ ; highmem.c
+ extern highmem_init
+
; fs.c
extern fs_init, searchdir, getfssec, mangle_name, load_config
extern unmangle_name, close_file
diff --git a/core/highmem.c b/core/highmem.c
new file mode 100644
index 0000000..ebf72bf
--- /dev/null
+++ b/core/highmem.c
@@ -0,0 +1,159 @@
+/*
+ * highmem.c
+ *
+ * Main use is to find the first contineous usable memory
+ * the upper memory (> 1MB)
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <core.h>
+
+struct e820range {
+ uint64_t start;
+ uint64_t length;
+ uint32_t type;
+} __attribute__ ((packed));
+
+struct e820range __lowmem E820Buf;
+
+static void *hex_dump(void *start, int dlen, const char *str)
+{
+ uint32_t *data = start;
+ uint32_t i;
+
+ printf("Dump info for %s:\n", str);
+ for (i = 0; i < dlen; i++)
+ printf(" %08x ", data[i]);
+ printf("\n");
+}
+
+/*
+ * Try e820 first, then e801, then 88 for INT 15h
+ */
+void highmem_init(void)
+{
+ char *buf = (char *)&E820Buf;
+ uint32_t start, len;
+ uint32_t end = 0;
+ uint32_t E820Max = 0xfff00000;
+ uint32_t E820Mem = 0x100000;
+ com32sys_t ireg, oreg;
+
+ memset(&ireg, 0, sizeof ireg);
+ memset(&oreg, 0, sizeof ireg);
+
+ ireg.eax.l = 0xe820;
+ ireg.ebx.l = 0;
+ ireg.ecx.l = 20;
+ ireg.edx.l = 0x534D4150; /* "SMAP" */
+
+ ireg.es = SEG(buf);
+ ireg.edi.l = OFFS(buf);
+
+ while (1) {
+ __intcall(0x15, &ireg, &oreg);
+
+ /*
+ printf("Start = %llx, length = %llx, type = %d, E820Mem = %x\n",
+ E820Buf.start,
+ E820Buf.length,
+ E820Buf.type,
+ E820Mem);
+ hex_dump(&oreg, 11, "oreg");
+ */
+
+ /* set the value in the first place */
+ ireg.ebx.l = oreg.ebx.l;
+
+ if ((oreg.eflags.l & EFLAGS_CF)) {
+ if (oreg.ebx.l)
+ break; /* we are done here */
+ else
+ goto no_e820;
+ }
+
+ /* return ebx == 0 means this is the last mmap desc */
+ if (!oreg.ebx.l)
+ break;
+
+ /* carry flag is not set */
+ if (oreg.eax.l != 0x534D4150 || oreg.ecx.l != 20)
+ goto no_e820;
+
+ if (E820Buf.start & 0xf00000000)
+ continue;
+
+ /* get 32 bits */
+ start = E820Buf.start & 0xffffffff;
+ len = E820Buf.length & 0xffffffff;
+
+ /* not ram */
+ if (E820Buf.type != 1) {
+ if (start > 0x100000 && start < E820Max)
+ E820Max = start;
+ continue;
+ }
+
+ /* is ram */
+ if (start > E820Mem)
+ continue;
+
+ /* no overflow */
+ end = start + len;
+ if (end > start) {
+ if (end > E820Mem) {
+ E820Mem = end;
+ ireg.ebx.l = 0;
+ }
+ continue;
+ }
+ }
+
+ goto done;
+
+no_e820:
+ memset(&ireg, 0, sizeof ireg);
+ ireg.eax.l = 0xE801;
+ __intcall(0x15, &ireg, &oreg);
+
+ /* only output value we care */
+ end = oreg.eax.l;
+
+ if ((oreg.eflags.l & EFLAGS_CF) || end > 0x3c00)
+ goto no_e801;
+
+ if (end < 0x3c00) {
+ end &= 0xffff;
+ end = end << 10;
+ end += 0x100000;
+ } else {
+ /* == 0x3c00 case */
+ end = oreg.ebx.w[0];
+ end = end << 16;
+ end += 16 << 20;
+ }
+ goto done;
+
+no_e801:
+ memset(&ireg, 0, sizeof ireg);
+ ireg.eax.l = 0x8800; /* ah == 0x88 */
+ __intcall(0x15, &ireg, &oreg);
+
+ if (oreg.eflags.l & EFLAGS_CF) {
+ printf("ERROR: Can't fine mem info from BIOS\n");
+ return;
+ }
+
+ end = oreg.eax.l;
+ if (end > 14 * 1024)
+ end = 14 * 1024;
+
+ end &= 0xffff;
+ end = end << 10;
+ end += 0x100000;
+done:
+ __com32.cs_memsize = end;
+ return;
+}
diff --git a/core/highmem.inc b/core/highmem.inc
deleted file mode 100644
index ea386ff..0000000
--- a/core/highmem.inc
+++ /dev/null
@@ -1,158 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; highmem.inc
-;;
-;; Probe for the size of high memory. This can be overridden by a
-;; mem= command on the command line while booting a new kernel.
-;;
-
- section .text16
-
-;
-; This is set up as a subroutine; it will set up the global variable
-; HighMemSize. All registers are preserved.
-;
-highmemsize:
- push es
- pushfd
- pushad
-
- push cs
- pop es
-
-;
-; First, try INT 15:E820 (get BIOS memory map)
-;
-; Note: we may have to scan this multiple times, because some (daft) BIOSes
-; report main memory as multiple contiguous ranges...
-;
-get_e820:
- mov dword [E820Max],-(1 << 20) ; Max amount of high memory
- mov dword [E820Mem],(1 << 20) ; End of detected high memory
-.start_over:
- mov di,E820Buf
- xor ax,ax
- mov cx,10
- rep stosw ; Clear buffer
- xor ebx,ebx ; Start with first record
- jmp short .do_e820 ; Skip "at end" check first time!
-.int_loop: and ebx,ebx ; If we're back at beginning...
- jz .e820_done ; ... we're done
-.do_e820: mov eax,0000E820h
- mov edx,534D4150h ; "SMAP" backwards
- xor ecx,ecx
- mov cl,20 ; ECX <- 20 (size of buffer)
- mov di,E820Buf
- int 15h
- jnc .no_carry
- ; If carry, ebx == 0 means error, ebx != 0 means we're done
- and ebx,ebx
- jnz .e820_done
- jmp no_e820
-.no_carry:
- cmp eax,534D4150h
- jne no_e820
- cmp cx,20
- jb no_e820
-
-;
-; Look for a memory block starting at <= 1 MB and continuing upward
-;
- cmp dword [E820Buf+4], byte 0
- ja .int_loop ; Start >= 4 GB?
- mov eax, [E820Buf]
- cmp dword [E820Buf+16],1
- je .is_ram ; Is it memory?
- ;
- ; Non-memory range. Remember this as a limit; some BIOSes get the length
- ; of primary RAM incorrect!
- ;
-.not_ram:
- cmp eax, (1 << 20)
- jb .int_loop ; Starts in lowmem region
- cmp eax,[E820Max]
- jae .int_loop ; Already above limit
- mov [E820Max],eax ; Set limit
- jmp .int_loop
-
-.is_ram:
- cmp eax,[E820Mem]
- ja .int_loop ; Not contiguous with our starting point
- add eax,[E820Buf+8]
- jc .overflow
- cmp dword [E820Buf+12],0
- je .nooverflow
-.overflow:
- or eax,-1
-.nooverflow:
- cmp eax,[E820Mem]
- jbe .int_loop ; All is below our baseline
- mov [E820Mem],eax
- jmp .start_over ; Start over in case we find an adjacent range
-
-.e820_done:
- mov eax,[E820Mem]
- cmp eax,[E820Max]
- jna .not_limited
- mov eax,[E820Max]
-.not_limited:
- cmp eax,(1 << 20)
- ja got_highmem ; Did we actually find memory?
- ; otherwise fall through
-
-;
-; INT 15:E820 failed. Try INT 15:E801.
-;
-no_e820:
- mov ax,0e801h ; Query high memory (semi-recent)
- int 15h
- jc no_e801
- cmp ax,3c00h
- ja no_e801 ; > 3C00h something's wrong with this call
- jb e801_hole ; If memory hole we can only use low part
-
- mov ax,bx
- shl eax,16 ; 64K chunks
- add eax,(16 << 20) ; Add first 16M
- jmp short got_highmem
-
-;
-; INT 15:E801 failed. Try INT 15:88.
-;
-no_e801:
- mov ah,88h ; Query high memory (oldest)
- int 15h
- cmp ax,14*1024 ; Don't trust memory >15M
- jna e801_hole
- mov ax,14*1024
-e801_hole:
- and eax,0ffffh
- shl eax,10 ; Convert from kilobytes
- add eax,(1 << 20) ; First megabyte
-got_highmem:
-%if HIGHMEM_SLOP != 0
- sub eax,HIGHMEM_SLOP
-%endif
- mov [HighMemSize],eax
- popad
- popfd
- pop es
- ret ; Done!
-
- section .bss16
- alignb 4
-E820Buf resd 5 ; INT 15:E820 data buffer
-E820Mem resd 1 ; Memory detected by E820
-E820Max resd 1 ; Is E820 memory capped?
-; HighMemSize is defined in com32.inc
--
1.6.0.4
More information about the Syslinux
mailing list