add malloc

Allocate the e820 map in the E-segment.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/Makefile b/Makefile
index 39a63bd..6db2104 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 obj-y = code16.o entry.o main.o string.o printf.o cstart.o fw_cfg.o
-obj-y += linuxboot.o
+obj-y += linuxboot.o malloc.o
 
 all-y = bios.bin
 all: $(all-y)
diff --git a/code16.c b/code16.c
index d8861de..f933915 100644
--- a/code16.c
+++ b/code16.c
@@ -1,4 +1,5 @@
 asm(".code16gcc");
+#include <stddef.h>
 #include "bios.h"
 #include "segment.h"
 #include "ioport.h"
@@ -23,32 +24,40 @@
 {
 	uint32_t v;
 
-	asm volatile("addr32 movl %%fs:%1,%0" : "=q" (v) : "m" (*(uint32_t *)addr));
+	asm volatile("addr32 movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
 
 	return v;
 }
 
-struct e820map e820;
+static inline uint16_t rdcs16(void *p)
+{
+	uint32_t addr = ((uintptr_t) p) & 65535;
+	uint16_t v;
+
+	asm volatile("addr32 movw %%cs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
+
+	return v;
+}
+
+uint16_t e820_seg;
 
 bioscall void e820_query_map(struct biosregs *regs)
 {
 	uint32_t map_size;
-	uint16_t fs_seg;
 	uint32_t ndx;
 
-	fs_seg		= flat_to_seg16((uintptr_t) &e820);
-	set_fs(fs_seg);
+	set_fs(rdcs16(&e820_seg));
 
 	ndx		= regs->ebx;
 
-	map_size	= rdfs32(flat_to_off16((uintptr_t) &e820.nr_map));
+	map_size	= rdfs32(offsetof(struct e820map, nr_map));
 
 	if (ndx < map_size) {
 		uint32_t start;
 		unsigned int i;
 		uint8_t *p;
 
-		start	= flat_to_off16((uintptr_t)&e820.map[ndx]);
+		start	= flat_to_off16(offsetof(struct e820map, map[ndx]));
 
 		p	= (void *) regs->edi;
 
diff --git a/flat.lds b/flat.lds
index d12b835..be84ec3 100644
--- a/flat.lds
+++ b/flat.lds
@@ -3,14 +3,16 @@
 SECTIONS
 {
     . = 1024K - 64K;
+    stext = .;
     .text : { *(.text.startup) *(.text) *(.text.*) }
-    . = ALIGN(4K);
+    . = ALIGN(16);
     .data : { *(.data) }
     . = ALIGN(16);
     .rodata : { *(.rodata) }
     . = ALIGN(16);
     .bss : { *(.bss) }
-    . = ALIGN(4K);
+    . = ALIGN(16);
+    edata = .;
     . = 1024K - 128;
     .init : {
 	*(.init);
diff --git a/include/bios.h b/include/bios.h
index 93c4c96..d3f9a22 100644
--- a/include/bios.h
+++ b/include/bios.h
@@ -38,7 +38,7 @@
 
 extern void boot_from_fwcfg(void);
 
-extern struct e820map e820;
+extern uint16_t e820_seg;
 
 #define ARRAY_SIZE(x)	(sizeof(x) / sizeof(x[0]))
 
diff --git a/include/e820.h b/include/e820.h
index 1dfd18f..085df6a 100644
--- a/include/e820.h
+++ b/include/e820.h
@@ -2,30 +2,6 @@
 #define _UAPI_ASM_X86_E820_H
 
 #define SMAP    0x534d4150	/* ASCII "SMAP" */
-#define E820MAP	0x2d0		/* our map */
-#define E820MAX	128		/* number of entries in E820MAP */
-
-/*
- * Legacy E820 BIOS limits us to 128 (E820MAX) nodes due to the
- * constrained space in the zeropage.  If we have more nodes than
- * that, and if we've booted off EFI firmware, then the EFI tables
- * passed us from the EFI firmware can list more nodes.  Size our
- * internal memory map tables to have room for these additional
- * nodes, based on up to three entries per node for which the
- * kernel was built: MAX_NUMNODES == (1 << CONFIG_NODES_SHIFT),
- * plus E820MAX, allowing space for the possible duplicate E820
- * entries that might need room in the same arrays, prior to the
- * call to sanitize_e820_map() to remove duplicates.  The allowance
- * of three memory map entries per node is "enough" entries for
- * the initial hardware platform motivating this mechanism to make
- * use of additional EFI map entries.  Future platforms may want
- * to allow more than three entries per node or otherwise refine
- * this size.
- */
-
-#define E820_X_MAX E820MAX
-
-#define E820NR	0x1e8		/* # entries in E820MAP */
 
 #define E820_RAM	1
 #define E820_RESERVED	2
@@ -50,7 +26,7 @@
 
 struct e820map {
 	uint32_t nr_map;
-	struct e820entry map[E820_X_MAX];
+	struct e820entry map[];
 };
 
 #define ISA_START_ADDRESS	0xa0000
diff --git a/include/string.h b/include/string.h
index 962b07e..9b0b8af 100644
--- a/include/string.h
+++ b/include/string.h
@@ -15,4 +15,7 @@
 void *memmove(void *dest, const void *src, size_t n);
 void *memchr(const void *s, int c, size_t n);
 
+void *malloc(int n);
+void *malloc_fseg(int n);
+
 #endif
diff --git a/main.c b/main.c
index 8b61caf..74c4057 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,5 @@
 #include "bios.h"
+#include "stdio.h"
 #include "e820.h"
 #include "pci.h"
 #include "string.h"
@@ -83,24 +84,31 @@
 {
 	int id = fw_cfg_file_id("etc/e820");
 	uint32_t size;
+	int nr_map;
+	struct e820map *e820;
 
 	if (id == -1)
 		panic();
 
 	size = fw_cfg_file_size(id);
-	e820.nr_map = size / sizeof(e820.map[0]) + 4;
+	nr_map = size / sizeof(e820->map[0]) + 4;
 	fw_cfg_file_select(id);
-	e820.map[0] = (struct e820entry)
+
+	e820 = malloc(offsetof(struct e820map, map[nr_map]));
+	e820->nr_map = nr_map;
+	e820->map[0] = (struct e820entry)
 		{ .addr = 0, .size = 639 * 1024, .type = E820_RAM }; /* low RAM */
-	e820.map[1] = (struct e820entry)
+	e820->map[1] = (struct e820entry)
 		{ .addr = 639 * 1024, .size = 1024, .type = E820_RESERVED }; /* EBDA */
-	e820.map[2] = (struct e820entry)
+	e820->map[2] = (struct e820entry)
 		{ .addr = 0xe0000, .size = 64 * 1024, .type = E820_NVS }; /* ACPI tables */
-	e820.map[3] = (struct e820entry)
+	e820->map[3] = (struct e820entry)
 		{ .addr = 0xf0000, .size = 64 * 1024, .type = E820_RESERVED }; /* firmware */
-	fw_cfg_read(&e820.map[4], size);
-	e820.map[4].addr = 1024 * 1024;
-	e820.map[4].size -= 1024 * 1024;
+	fw_cfg_read(&e820->map[4], size);
+	e820->map[4].addr = 1024 * 1024;
+	e820->map[4].size -= 1024 * 1024;
+
+	e820_seg = ((uintptr_t) e820) >> 4;
 }
 
 int main(void)
diff --git a/malloc.c b/malloc.c
new file mode 100644
index 0000000..3ab95ed
--- /dev/null
+++ b/malloc.c
@@ -0,0 +1,21 @@
+#include <inttypes.h>
+#include "string.h"
+
+extern uint8_t edata;
+static uint8_t *fseg_base = &edata;
+
+extern uint8_t stext;
+static uint8_t *malloc_top = &stext;
+
+void *malloc(int n)
+{
+	malloc_top -= (n + 15) & -16;
+	return malloc_top;
+}
+
+void *malloc_fseg(int n)
+{
+	void *p = fseg_base;
+	fseg_base += (n + 15) & -16;
+	return p;
+}