[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