aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2015-05-21 10:26:49 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2015-05-21 11:44:57 +0200
commitfa9ea2e622eb105fb77f1f09e3194bfc05db7c5e (patch)
treebe8d9bd2dd39fb6cd6c090f8c7bbbf1d43a39f90
parentbd363b8030716a759823d8828690e49ad4d25f96 (diff)
downloadqboot-fa9ea2e622eb105fb77f1f09e3194bfc05db7c5e.zip
qboot-fa9ea2e622eb105fb77f1f09e3194bfc05db7c5e.tar.gz
qboot-fa9ea2e622eb105fb77f1f09e3194bfc05db7c5e.tar.bz2
add malloc
Allocate the e820 map in the E-segment. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--Makefile2
-rw-r--r--code16.c23
-rw-r--r--flat.lds6
-rw-r--r--include/bios.h2
-rw-r--r--include/e820.h26
-rw-r--r--include/string.h3
-rw-r--r--main.c24
-rw-r--r--malloc.c21
8 files changed, 63 insertions, 44 deletions
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 @@ static inline uint32_t rdfs32(unsigned long addr)
{
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 @@ OUTPUT_ARCH(i386)
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 bios_int15(void);
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 e820entry {
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 @@ int memcmp(const void *s1, const void *s2, size_t n);
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 @@ static void extract_e820(void)
{
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;
+}