diff options
Diffstat (limited to 'meta/recipes-devtools/syslinux/files/0002-memscan-build-a-linked-list-of-memory-scanners.patch')
-rw-r--r-- | meta/recipes-devtools/syslinux/files/0002-memscan-build-a-linked-list-of-memory-scanners.patch | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/meta/recipes-devtools/syslinux/files/0002-memscan-build-a-linked-list-of-memory-scanners.patch b/meta/recipes-devtools/syslinux/files/0002-memscan-build-a-linked-list-of-memory-scanners.patch new file mode 100644 index 0000000000..48d3955910 --- /dev/null +++ b/meta/recipes-devtools/syslinux/files/0002-memscan-build-a-linked-list-of-memory-scanners.patch @@ -0,0 +1,450 @@ +Upstream-Status: Backport [787d7e568fe08d7080d2cd03cd9ee27c327eca67] +Signed-off-by: Jonathan Liu <net147@gmail.com> + +From 2e05f34c0c5bc0144bb203a169009dfb6837b4e3 Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Wed, 17 Jul 2013 12:15:16 +0100 +Subject: [PATCH 2/4] memscan: build a linked list of memory scanners + +By registering memory scanners at runtime we can support multiple memory +scanner functions, which helps us to isolate them and keep things +modular, only registering them for specific platform/derivative +combinations. This is preparation for adding a memory scanner that is +specific to PXELINUX on bios and understands when the memory region +occupied by the PXE stack can be reused. + +Signed-off-by: Matt Fleming <matt.fleming@intel.com> + +Conflicts: + com32/include/syslinux/memscan.h + com32/lib/syslinux/memscan.c +--- + com32/include/syslinux/firmware.h | 4 +- + com32/include/syslinux/memscan.h | 14 +++- + com32/lib/syslinux/memscan.c | 143 +++++++------------------------------- + core/bios.c | 125 ++++++++++++++++++++++++++++++++- + efi/main.c | 14 ++-- + 5 files changed, 173 insertions(+), 127 deletions(-) + +diff --git a/com32/include/syslinux/firmware.h b/com32/include/syslinux/firmware.h +index 4a43c86..6cc06a0 100644 +--- a/com32/include/syslinux/firmware.h ++++ b/com32/include/syslinux/firmware.h +@@ -1,7 +1,8 @@ + #ifndef _SYSLINUX_FIRMWARE_H + #define _SYSLINUX_FIRMWARE_H + +-#include <syslinux/memscan.h> ++#include <inttypes.h> ++#include <stdbool.h> + + struct term_state; + +@@ -42,7 +43,6 @@ struct mem_ops { + void *(*malloc)(size_t, enum heap, size_t); + void *(*realloc)(void *, size_t); + void (*free)(void *); +- int (*scan_memory)(scan_memory_callback_t, void *); + }; + + struct initramfs; +diff --git a/com32/include/syslinux/memscan.h b/com32/include/syslinux/memscan.h +index c3ebf84..ab78e28 100644 +--- a/com32/include/syslinux/memscan.h ++++ b/com32/include/syslinux/memscan.h +@@ -29,11 +29,19 @@ + #ifndef _SYSLINUX_MEMSCAN_H + #define _SYSLINUX_MEMSCAN_H + +-#include <stdbool.h> ++#include <linux/list.h> + #include <syslinux/movebits.h> /* addr_t */ + +-typedef int (*scan_memory_callback_t) (void *, addr_t, addr_t, bool); ++typedef int (*scan_memory_callback_t) (void *, addr_t, addr_t, ++ enum syslinux_memmap_types type); ++ ++struct syslinux_memscan { ++ int (*func)(scan_memory_callback_t callback, void *data); ++ struct list_head next; ++}; ++ ++void syslinux_memscan_add(struct syslinux_memscan *entry); ++int syslinux_memscan_new(int (*func)(scan_memory_callback_t cb, void *data)); + int syslinux_scan_memory(scan_memory_callback_t callback, void *data); +-int bios_scan_memory(scan_memory_callback_t callback, void *data); + + #endif /* _SYSLINUX_MEMSCAN_H */ +diff --git a/com32/lib/syslinux/memscan.c b/com32/lib/syslinux/memscan.c +index 0ff25d7..fdb7274 100644 +--- a/com32/lib/syslinux/memscan.c ++++ b/com32/lib/syslinux/memscan.c +@@ -32,133 +32,44 @@ + * Query the system for free memory + */ + +-#include <assert.h> +-#include <stdbool.h> +-#include <stdlib.h> +-#include <string.h> +-#include <inttypes.h> +-#include <com32.h> +- + #include <syslinux/memscan.h> +-#include <syslinux/firmware.h> + +-struct e820_entry { +- uint64_t start; +- uint64_t len; +- uint32_t type; +-}; ++static LIST_HEAD(syslinux_memscan_head); + +-int bios_scan_memory(scan_memory_callback_t callback, void *data) ++/* ++ * Add a memscan entry to the list. ++ */ ++void syslinux_memscan_add(struct syslinux_memscan *entry) + { +- static com32sys_t ireg; +- com32sys_t oreg; +- struct e820_entry *e820buf; +- uint64_t start, len, maxlen; +- int memfound = 0; +- int rv; +- addr_t dosmem; +- const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ ++ list_add(&entry->next, &syslinux_memscan_head); ++} + +- /* Use INT 12h to get DOS memory */ +- __intcall(0x12, &__com32_zero_regs, &oreg); +- dosmem = oreg.eax.w[0] << 10; +- if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { +- /* INT 12h reports nonsense... now what? */ +- uint16_t ebda_seg = *(uint16_t *) 0x40e; +- if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) +- dosmem = ebda_seg << 4; +- else +- dosmem = 640 * 1024; /* Hope for the best... */ +- } +- rv = callback(data, bios_data, dosmem - bios_data, true); +- if (rv) +- return rv; ++/* ++ * Build a new memscan entry and add it to the list. ++ */ ++int syslinux_memscan_new(int func(scan_memory_callback_t, void *data)) ++{ ++ struct syslinux_memscan *entry; + +- /* First try INT 15h AX=E820h */ +- e820buf = lzalloc(sizeof *e820buf); +- if (!e820buf) ++ entry = malloc(sizeof *entry); ++ if (!entry) + return -1; + +- ireg.eax.l = 0xe820; +- ireg.edx.l = 0x534d4150; +- ireg.ebx.l = 0; +- ireg.ecx.l = sizeof(*e820buf); +- ireg.es = SEG(e820buf); +- ireg.edi.w[0] = OFFS(e820buf); +- +- do { +- __intcall(0x15, &ireg, &oreg); +- +- if ((oreg.eflags.l & EFLAGS_CF) || +- (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) +- break; +- +- start = e820buf->start; +- len = e820buf->len; +- +- if (start < 0x100000000ULL) { +- /* Don't rely on E820 being valid for low memory. Doing so +- could mean stuff like overwriting the PXE stack even when +- using "keeppxe", etc. */ +- if (start < 0x100000ULL) { +- if (len > 0x100000ULL - start) +- len -= 0x100000ULL - start; +- else +- len = 0; +- start = 0x100000ULL; +- } +- +- maxlen = 0x100000000ULL - start; +- if (len > maxlen) +- len = maxlen; +- +- if (len) { +- rv = callback(data, (addr_t) start, (addr_t) len, +- e820buf->type == 1); +- if (rv) +- return rv; +- memfound = 1; +- } +- } +- +- ireg.ebx.l = oreg.ebx.l; +- } while (oreg.ebx.l); +- +- lfree(e820buf); +- +- if (memfound) +- return 0; +- +- /* Next try INT 15h AX=E801h */ +- ireg.eax.w[0] = 0xe801; +- __intcall(0x15, &ireg, &oreg); +- +- if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { +- rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); +- if (rv) +- return rv; +- +- if (oreg.edx.w[0]) { +- rv = callback(data, (addr_t) 16 << 20, oreg.edx.w[0] << 16, true); +- if (rv) +- return rv; +- } +- +- return 0; +- } +- +- /* Finally try INT 15h AH=88h */ +- ireg.eax.w[0] = 0x8800; +- if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { +- rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); +- if (rv) +- return rv; +- } +- ++ entry->func = func; ++ syslinux_memscan_add(entry); + return 0; + } + + int syslinux_scan_memory(scan_memory_callback_t callback, void *data) + { +- return firmware->mem->scan_memory(callback, data); ++ struct syslinux_memscan *entry; ++ int rv = 0; ++ ++ list_for_each_entry(entry, &syslinux_memscan_head, next) { ++ rv = entry->func(callback, data); ++ if (rv) ++ break; ++ } ++ ++ return rv; + } +diff --git a/core/bios.c b/core/bios.c +index 53223e8..5344833 100644 +--- a/core/bios.c ++++ b/core/bios.c +@@ -501,6 +501,129 @@ static inline void bios_timer_init(void) + + extern uint16_t *bios_free_mem; + ++struct e820_entry { ++ uint64_t start; ++ uint64_t len; ++ uint32_t type; ++}; ++ ++static int bios_scan_memory(scan_memory_callback_t callback, void *data) ++{ ++ static com32sys_t ireg; ++ com32sys_t oreg; ++ struct e820_entry *e820buf; ++ uint64_t start, len, maxlen; ++ int memfound = 0; ++ int rv; ++ addr_t dosmem; ++ const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ ++ ++ /* Use INT 12h to get DOS memory */ ++ __intcall(0x12, &__com32_zero_regs, &oreg); ++ dosmem = oreg.eax.w[0] << 10; ++ if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { ++ /* INT 12h reports nonsense... now what? */ ++ uint16_t ebda_seg = *(uint16_t *) 0x40e; ++ if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) ++ dosmem = ebda_seg << 4; ++ else ++ dosmem = 640 * 1024; /* Hope for the best... */ ++ } ++ rv = callback(data, bios_data, dosmem - bios_data, SMT_FREE); ++ if (rv) ++ return rv; ++ ++ /* First try INT 15h AX=E820h */ ++ e820buf = lzalloc(sizeof *e820buf); ++ if (!e820buf) ++ return -1; ++ ++ ireg.eax.l = 0xe820; ++ ireg.edx.l = 0x534d4150; ++ ireg.ebx.l = 0; ++ ireg.ecx.l = sizeof(*e820buf); ++ ireg.es = SEG(e820buf); ++ ireg.edi.w[0] = OFFS(e820buf); ++ ++ do { ++ __intcall(0x15, &ireg, &oreg); ++ ++ if ((oreg.eflags.l & EFLAGS_CF) || ++ (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) ++ break; ++ ++ start = e820buf->start; ++ len = e820buf->len; ++ ++ if (start < 0x100000000ULL) { ++ /* Don't rely on E820 being valid for low memory. Doing so ++ could mean stuff like overwriting the PXE stack even when ++ using "keeppxe", etc. */ ++ if (start < 0x100000ULL) { ++ if (len > 0x100000ULL - start) ++ len -= 0x100000ULL - start; ++ else ++ len = 0; ++ start = 0x100000ULL; ++ } ++ ++ maxlen = 0x100000000ULL - start; ++ if (len > maxlen) ++ len = maxlen; ++ ++ if (len) { ++ enum syslinux_memmap_types type; ++ ++ type = e820buf->type == 1 ? SMT_FREE : SMT_RESERVED; ++ rv = callback(data, (addr_t) start, (addr_t) len, type); ++ if (rv) ++ return rv; ++ memfound = 1; ++ } ++ } ++ ++ ireg.ebx.l = oreg.ebx.l; ++ } while (oreg.ebx.l); ++ ++ lfree(e820buf); ++ ++ if (memfound) ++ return 0; ++ ++ /* Next try INT 15h AX=E801h */ ++ ireg.eax.w[0] = 0xe801; ++ __intcall(0x15, &ireg, &oreg); ++ ++ if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { ++ rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, SMT_FREE); ++ if (rv) ++ return rv; ++ ++ if (oreg.edx.w[0]) { ++ rv = callback(data, (addr_t) 16 << 20, ++ oreg.edx.w[0] << 16, SMT_FREE); ++ if (rv) ++ return rv; ++ } ++ ++ return 0; ++ } ++ ++ /* Finally try INT 15h AH=88h */ ++ ireg.eax.w[0] = 0x8800; ++ if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { ++ rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, SMT_FREE); ++ if (rv) ++ return rv; ++ } ++ ++ return 0; ++} ++ ++static struct syslinux_memscan bios_memscan = { ++ .func = bios_scan_memory, ++}; ++ + void bios_init(void) + { + int i; +@@ -515,6 +638,7 @@ void bios_init(void) + + /* Init the memory subsystem */ + bios_free_mem = (uint16_t *)0x413; ++ syslinux_memscan_add(&bios_memscan); + mem_init(); + + /* CPU-dependent initialization and related checks. */ +@@ -534,7 +658,6 @@ struct mem_ops bios_mem_ops = { + .malloc = bios_malloc, + .realloc = bios_realloc, + .free = bios_free, +- .scan_memory = bios_scan_memory, + }; + + struct firmware bios_fw = { +diff --git a/efi/main.c b/efi/main.c +index 13b9403..fb8cf05 100644 +--- a/efi/main.c ++++ b/efi/main.c +@@ -296,21 +296,21 @@ int efi_scan_memory(scan_memory_callback_t callback, void *data) + for (i = 0; i < nr_entries; bufpos += desc_sz, i++) { + EFI_MEMORY_DESCRIPTOR *m; + UINT64 region_sz; +- int valid; ++ enum syslinux_memmap_types type; + + m = (EFI_MEMORY_DESCRIPTOR *)bufpos; + region_sz = m->NumberOfPages * EFI_PAGE_SIZE; + + switch (m->Type) { + case EfiConventionalMemory: +- valid = 1; ++ type = SMT_FREE; + break; + default: +- valid = 0; ++ type = SMT_RESERVED; + break; + } + +- rv = callback(data, m->PhysicalStart, region_sz, valid); ++ rv = callback(data, m->PhysicalStart, region_sz, type); + if (rv) + break; + } +@@ -319,11 +319,16 @@ int efi_scan_memory(scan_memory_callback_t callback, void *data) + return rv; + } + ++static struct syslinux_memscan efi_memscan = { ++ .func = efi_scan_memory, ++}; ++ + extern uint16_t *bios_free_mem; + void efi_init(void) + { + /* XXX timer */ + *bios_free_mem = 0; ++ syslinux_memscan_add(&efi_memscan); + mem_init(); + } + +@@ -1103,7 +1108,6 @@ struct mem_ops efi_mem_ops = { + .malloc = efi_malloc, + .realloc = efi_realloc, + .free = efi_free, +- .scan_memory = efi_scan_memory, + }; + + struct firmware efi_fw = { +-- +1.8.5.3 + |