diff options
| author | Jonathan Liu <net147@gmail.com> | 2014-02-02 15:58:52 +1100 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-02-02 11:22:08 +0000 |
| commit | 4a8ddd8379527705ec8828c9c8e1c9b29a6a4152 (patch) | |
| tree | 99fb2b31dc0c55d9cddc0680a4616af09ced05e1 | |
| parent | 1ae1b2885177e29324b6758cb8c123ab7cdbaf9b (diff) | |
| download | poky-4a8ddd8379527705ec8828c9c8e1c9b29a6a4152.tar.gz | |
syslinux: fix booting memtest86+ using pxelinux regression
After syslinux was updated from 4.07 to 6.01, booting memtest86+ using
pxelinux would fail:
PXELINUX 6.01 2013-07-04 Copyright (C) 1994-2013 H. Peter Anvin et al
Loading memtest86... ok
Booting kernel failed: invalid argument
This backports the necessary upstream patches to allow memtest86+ to
boot using pxelinux again.
[YOCTO #5501]
(From OE-Core rev: ed9ccb8622b347173602be8b2126324d4fdf54d8)
Signed-off-by: Jonathan Liu <net147@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
5 files changed, 657 insertions, 1 deletions
diff --git a/meta/recipes-devtools/syslinux/files/0001-movebits-Add-SMT_TERMINAL-a-last-resort-region-type.patch b/meta/recipes-devtools/syslinux/files/0001-movebits-Add-SMT_TERMINAL-a-last-resort-region-type.patch new file mode 100644 index 0000000000..fb03bbfe2c --- /dev/null +++ b/meta/recipes-devtools/syslinux/files/0001-movebits-Add-SMT_TERMINAL-a-last-resort-region-type.patch | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | Upstream-Status: Backport [ba638fd9bf72b0c786c88909014136cfa641a147] | ||
| 2 | Signed-off-by: Jonathan Liu <net147@gmail.com> | ||
| 3 | |||
| 4 | From b663fd7257481438256f8267831dc10b06363b22 Mon Sep 17 00:00:00 2001 | ||
| 5 | From: Matt Fleming <matt.fleming@intel.com> | ||
| 6 | Date: Tue, 16 Jul 2013 22:16:11 +0100 | ||
| 7 | Subject: [PATCH 1/4] movebits: Add SMT_TERMINAL - a last resort region type | ||
| 8 | |||
| 9 | Some memory regions are usable, but only as a last resort just before we | ||
| 10 | hand over control to a kernel image. Add the necessary movebits | ||
| 11 | infrastructure to use these regions when all other options have been | ||
| 12 | exhausted. | ||
| 13 | |||
| 14 | Signed-off-by: Matt Fleming <matt.fleming@intel.com> | ||
| 15 | |||
| 16 | Conflicts: | ||
| 17 | com32/lib/syslinux/zonelist.c | ||
| 18 | --- | ||
| 19 | com32/include/syslinux/movebits.h | 1 + | ||
| 20 | com32/lib/syslinux/movebits.c | 2 +- | ||
| 21 | 2 files changed, 2 insertions(+), 1 deletion(-) | ||
| 22 | |||
| 23 | diff --git a/com32/include/syslinux/movebits.h b/com32/include/syslinux/movebits.h | ||
| 24 | index 8bcdf3e..114a896 100644 | ||
| 25 | --- a/com32/include/syslinux/movebits.h | ||
| 26 | +++ b/com32/include/syslinux/movebits.h | ||
| 27 | @@ -34,6 +34,7 @@ enum syslinux_memmap_types { | ||
| 28 | SMT_RESERVED, /* Unusable memory */ | ||
| 29 | SMT_ALLOC, /* Memory allocated by user */ | ||
| 30 | SMT_ZERO, /* Memory that should be zeroed */ | ||
| 31 | + SMT_TERMINAL, /* Memory to be used as a last resort */ | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct syslinux_memmap { | ||
| 35 | diff --git a/com32/lib/syslinux/movebits.c b/com32/lib/syslinux/movebits.c | ||
| 36 | index 7a05f3c..8ffdc63 100644 | ||
| 37 | --- a/com32/lib/syslinux/movebits.c | ||
| 38 | +++ b/com32/lib/syslinux/movebits.c | ||
| 39 | @@ -160,7 +160,7 @@ static const struct syslinux_memmap *is_free_zone(const struct syslinux_memmap | ||
| 40 | if (list->start <= start) { | ||
| 41 | if (llast >= last) { | ||
| 42 | /* Chunk has a single, well-defined type */ | ||
| 43 | - if (list->type == SMT_FREE) { | ||
| 44 | + if (list->type == SMT_FREE || list->type == SMT_TERMINAL) { | ||
| 45 | dprintf("F: 0x%08x bytes at 0x%08x\n", | ||
| 46 | list->next->start, list->start); | ||
| 47 | return list; /* It's free */ | ||
| 48 | -- | ||
| 49 | 1.8.5.3 | ||
| 50 | |||
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 @@ | |||
| 1 | Upstream-Status: Backport [787d7e568fe08d7080d2cd03cd9ee27c327eca67] | ||
| 2 | Signed-off-by: Jonathan Liu <net147@gmail.com> | ||
| 3 | |||
| 4 | From 2e05f34c0c5bc0144bb203a169009dfb6837b4e3 Mon Sep 17 00:00:00 2001 | ||
| 5 | From: Matt Fleming <matt.fleming@intel.com> | ||
| 6 | Date: Wed, 17 Jul 2013 12:15:16 +0100 | ||
| 7 | Subject: [PATCH 2/4] memscan: build a linked list of memory scanners | ||
| 8 | |||
| 9 | By registering memory scanners at runtime we can support multiple memory | ||
| 10 | scanner functions, which helps us to isolate them and keep things | ||
| 11 | modular, only registering them for specific platform/derivative | ||
| 12 | combinations. This is preparation for adding a memory scanner that is | ||
| 13 | specific to PXELINUX on bios and understands when the memory region | ||
| 14 | occupied by the PXE stack can be reused. | ||
| 15 | |||
| 16 | Signed-off-by: Matt Fleming <matt.fleming@intel.com> | ||
| 17 | |||
| 18 | Conflicts: | ||
| 19 | com32/include/syslinux/memscan.h | ||
| 20 | com32/lib/syslinux/memscan.c | ||
| 21 | --- | ||
| 22 | com32/include/syslinux/firmware.h | 4 +- | ||
| 23 | com32/include/syslinux/memscan.h | 14 +++- | ||
| 24 | com32/lib/syslinux/memscan.c | 143 +++++++------------------------------- | ||
| 25 | core/bios.c | 125 ++++++++++++++++++++++++++++++++- | ||
| 26 | efi/main.c | 14 ++-- | ||
| 27 | 5 files changed, 173 insertions(+), 127 deletions(-) | ||
| 28 | |||
| 29 | diff --git a/com32/include/syslinux/firmware.h b/com32/include/syslinux/firmware.h | ||
| 30 | index 4a43c86..6cc06a0 100644 | ||
| 31 | --- a/com32/include/syslinux/firmware.h | ||
| 32 | +++ b/com32/include/syslinux/firmware.h | ||
| 33 | @@ -1,7 +1,8 @@ | ||
| 34 | #ifndef _SYSLINUX_FIRMWARE_H | ||
| 35 | #define _SYSLINUX_FIRMWARE_H | ||
| 36 | |||
| 37 | -#include <syslinux/memscan.h> | ||
| 38 | +#include <inttypes.h> | ||
| 39 | +#include <stdbool.h> | ||
| 40 | |||
| 41 | struct term_state; | ||
| 42 | |||
| 43 | @@ -42,7 +43,6 @@ struct mem_ops { | ||
| 44 | void *(*malloc)(size_t, enum heap, size_t); | ||
| 45 | void *(*realloc)(void *, size_t); | ||
| 46 | void (*free)(void *); | ||
| 47 | - int (*scan_memory)(scan_memory_callback_t, void *); | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct initramfs; | ||
| 51 | diff --git a/com32/include/syslinux/memscan.h b/com32/include/syslinux/memscan.h | ||
| 52 | index c3ebf84..ab78e28 100644 | ||
| 53 | --- a/com32/include/syslinux/memscan.h | ||
| 54 | +++ b/com32/include/syslinux/memscan.h | ||
| 55 | @@ -29,11 +29,19 @@ | ||
| 56 | #ifndef _SYSLINUX_MEMSCAN_H | ||
| 57 | #define _SYSLINUX_MEMSCAN_H | ||
| 58 | |||
| 59 | -#include <stdbool.h> | ||
| 60 | +#include <linux/list.h> | ||
| 61 | #include <syslinux/movebits.h> /* addr_t */ | ||
| 62 | |||
| 63 | -typedef int (*scan_memory_callback_t) (void *, addr_t, addr_t, bool); | ||
| 64 | +typedef int (*scan_memory_callback_t) (void *, addr_t, addr_t, | ||
| 65 | + enum syslinux_memmap_types type); | ||
| 66 | + | ||
| 67 | +struct syslinux_memscan { | ||
| 68 | + int (*func)(scan_memory_callback_t callback, void *data); | ||
| 69 | + struct list_head next; | ||
| 70 | +}; | ||
| 71 | + | ||
| 72 | +void syslinux_memscan_add(struct syslinux_memscan *entry); | ||
| 73 | +int syslinux_memscan_new(int (*func)(scan_memory_callback_t cb, void *data)); | ||
| 74 | int syslinux_scan_memory(scan_memory_callback_t callback, void *data); | ||
| 75 | -int bios_scan_memory(scan_memory_callback_t callback, void *data); | ||
| 76 | |||
| 77 | #endif /* _SYSLINUX_MEMSCAN_H */ | ||
| 78 | diff --git a/com32/lib/syslinux/memscan.c b/com32/lib/syslinux/memscan.c | ||
| 79 | index 0ff25d7..fdb7274 100644 | ||
| 80 | --- a/com32/lib/syslinux/memscan.c | ||
| 81 | +++ b/com32/lib/syslinux/memscan.c | ||
| 82 | @@ -32,133 +32,44 @@ | ||
| 83 | * Query the system for free memory | ||
| 84 | */ | ||
| 85 | |||
| 86 | -#include <assert.h> | ||
| 87 | -#include <stdbool.h> | ||
| 88 | -#include <stdlib.h> | ||
| 89 | -#include <string.h> | ||
| 90 | -#include <inttypes.h> | ||
| 91 | -#include <com32.h> | ||
| 92 | - | ||
| 93 | #include <syslinux/memscan.h> | ||
| 94 | -#include <syslinux/firmware.h> | ||
| 95 | |||
| 96 | -struct e820_entry { | ||
| 97 | - uint64_t start; | ||
| 98 | - uint64_t len; | ||
| 99 | - uint32_t type; | ||
| 100 | -}; | ||
| 101 | +static LIST_HEAD(syslinux_memscan_head); | ||
| 102 | |||
| 103 | -int bios_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 104 | +/* | ||
| 105 | + * Add a memscan entry to the list. | ||
| 106 | + */ | ||
| 107 | +void syslinux_memscan_add(struct syslinux_memscan *entry) | ||
| 108 | { | ||
| 109 | - static com32sys_t ireg; | ||
| 110 | - com32sys_t oreg; | ||
| 111 | - struct e820_entry *e820buf; | ||
| 112 | - uint64_t start, len, maxlen; | ||
| 113 | - int memfound = 0; | ||
| 114 | - int rv; | ||
| 115 | - addr_t dosmem; | ||
| 116 | - const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ | ||
| 117 | + list_add(&entry->next, &syslinux_memscan_head); | ||
| 118 | +} | ||
| 119 | |||
| 120 | - /* Use INT 12h to get DOS memory */ | ||
| 121 | - __intcall(0x12, &__com32_zero_regs, &oreg); | ||
| 122 | - dosmem = oreg.eax.w[0] << 10; | ||
| 123 | - if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { | ||
| 124 | - /* INT 12h reports nonsense... now what? */ | ||
| 125 | - uint16_t ebda_seg = *(uint16_t *) 0x40e; | ||
| 126 | - if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) | ||
| 127 | - dosmem = ebda_seg << 4; | ||
| 128 | - else | ||
| 129 | - dosmem = 640 * 1024; /* Hope for the best... */ | ||
| 130 | - } | ||
| 131 | - rv = callback(data, bios_data, dosmem - bios_data, true); | ||
| 132 | - if (rv) | ||
| 133 | - return rv; | ||
| 134 | +/* | ||
| 135 | + * Build a new memscan entry and add it to the list. | ||
| 136 | + */ | ||
| 137 | +int syslinux_memscan_new(int func(scan_memory_callback_t, void *data)) | ||
| 138 | +{ | ||
| 139 | + struct syslinux_memscan *entry; | ||
| 140 | |||
| 141 | - /* First try INT 15h AX=E820h */ | ||
| 142 | - e820buf = lzalloc(sizeof *e820buf); | ||
| 143 | - if (!e820buf) | ||
| 144 | + entry = malloc(sizeof *entry); | ||
| 145 | + if (!entry) | ||
| 146 | return -1; | ||
| 147 | |||
| 148 | - ireg.eax.l = 0xe820; | ||
| 149 | - ireg.edx.l = 0x534d4150; | ||
| 150 | - ireg.ebx.l = 0; | ||
| 151 | - ireg.ecx.l = sizeof(*e820buf); | ||
| 152 | - ireg.es = SEG(e820buf); | ||
| 153 | - ireg.edi.w[0] = OFFS(e820buf); | ||
| 154 | - | ||
| 155 | - do { | ||
| 156 | - __intcall(0x15, &ireg, &oreg); | ||
| 157 | - | ||
| 158 | - if ((oreg.eflags.l & EFLAGS_CF) || | ||
| 159 | - (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) | ||
| 160 | - break; | ||
| 161 | - | ||
| 162 | - start = e820buf->start; | ||
| 163 | - len = e820buf->len; | ||
| 164 | - | ||
| 165 | - if (start < 0x100000000ULL) { | ||
| 166 | - /* Don't rely on E820 being valid for low memory. Doing so | ||
| 167 | - could mean stuff like overwriting the PXE stack even when | ||
| 168 | - using "keeppxe", etc. */ | ||
| 169 | - if (start < 0x100000ULL) { | ||
| 170 | - if (len > 0x100000ULL - start) | ||
| 171 | - len -= 0x100000ULL - start; | ||
| 172 | - else | ||
| 173 | - len = 0; | ||
| 174 | - start = 0x100000ULL; | ||
| 175 | - } | ||
| 176 | - | ||
| 177 | - maxlen = 0x100000000ULL - start; | ||
| 178 | - if (len > maxlen) | ||
| 179 | - len = maxlen; | ||
| 180 | - | ||
| 181 | - if (len) { | ||
| 182 | - rv = callback(data, (addr_t) start, (addr_t) len, | ||
| 183 | - e820buf->type == 1); | ||
| 184 | - if (rv) | ||
| 185 | - return rv; | ||
| 186 | - memfound = 1; | ||
| 187 | - } | ||
| 188 | - } | ||
| 189 | - | ||
| 190 | - ireg.ebx.l = oreg.ebx.l; | ||
| 191 | - } while (oreg.ebx.l); | ||
| 192 | - | ||
| 193 | - lfree(e820buf); | ||
| 194 | - | ||
| 195 | - if (memfound) | ||
| 196 | - return 0; | ||
| 197 | - | ||
| 198 | - /* Next try INT 15h AX=E801h */ | ||
| 199 | - ireg.eax.w[0] = 0xe801; | ||
| 200 | - __intcall(0x15, &ireg, &oreg); | ||
| 201 | - | ||
| 202 | - if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { | ||
| 203 | - rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); | ||
| 204 | - if (rv) | ||
| 205 | - return rv; | ||
| 206 | - | ||
| 207 | - if (oreg.edx.w[0]) { | ||
| 208 | - rv = callback(data, (addr_t) 16 << 20, oreg.edx.w[0] << 16, true); | ||
| 209 | - if (rv) | ||
| 210 | - return rv; | ||
| 211 | - } | ||
| 212 | - | ||
| 213 | - return 0; | ||
| 214 | - } | ||
| 215 | - | ||
| 216 | - /* Finally try INT 15h AH=88h */ | ||
| 217 | - ireg.eax.w[0] = 0x8800; | ||
| 218 | - if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { | ||
| 219 | - rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); | ||
| 220 | - if (rv) | ||
| 221 | - return rv; | ||
| 222 | - } | ||
| 223 | - | ||
| 224 | + entry->func = func; | ||
| 225 | + syslinux_memscan_add(entry); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | int syslinux_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 230 | { | ||
| 231 | - return firmware->mem->scan_memory(callback, data); | ||
| 232 | + struct syslinux_memscan *entry; | ||
| 233 | + int rv = 0; | ||
| 234 | + | ||
| 235 | + list_for_each_entry(entry, &syslinux_memscan_head, next) { | ||
| 236 | + rv = entry->func(callback, data); | ||
| 237 | + if (rv) | ||
| 238 | + break; | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + return rv; | ||
| 242 | } | ||
| 243 | diff --git a/core/bios.c b/core/bios.c | ||
| 244 | index 53223e8..5344833 100644 | ||
| 245 | --- a/core/bios.c | ||
| 246 | +++ b/core/bios.c | ||
| 247 | @@ -501,6 +501,129 @@ static inline void bios_timer_init(void) | ||
| 248 | |||
| 249 | extern uint16_t *bios_free_mem; | ||
| 250 | |||
| 251 | +struct e820_entry { | ||
| 252 | + uint64_t start; | ||
| 253 | + uint64_t len; | ||
| 254 | + uint32_t type; | ||
| 255 | +}; | ||
| 256 | + | ||
| 257 | +static int bios_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 258 | +{ | ||
| 259 | + static com32sys_t ireg; | ||
| 260 | + com32sys_t oreg; | ||
| 261 | + struct e820_entry *e820buf; | ||
| 262 | + uint64_t start, len, maxlen; | ||
| 263 | + int memfound = 0; | ||
| 264 | + int rv; | ||
| 265 | + addr_t dosmem; | ||
| 266 | + const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ | ||
| 267 | + | ||
| 268 | + /* Use INT 12h to get DOS memory */ | ||
| 269 | + __intcall(0x12, &__com32_zero_regs, &oreg); | ||
| 270 | + dosmem = oreg.eax.w[0] << 10; | ||
| 271 | + if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { | ||
| 272 | + /* INT 12h reports nonsense... now what? */ | ||
| 273 | + uint16_t ebda_seg = *(uint16_t *) 0x40e; | ||
| 274 | + if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) | ||
| 275 | + dosmem = ebda_seg << 4; | ||
| 276 | + else | ||
| 277 | + dosmem = 640 * 1024; /* Hope for the best... */ | ||
| 278 | + } | ||
| 279 | + rv = callback(data, bios_data, dosmem - bios_data, SMT_FREE); | ||
| 280 | + if (rv) | ||
| 281 | + return rv; | ||
| 282 | + | ||
| 283 | + /* First try INT 15h AX=E820h */ | ||
| 284 | + e820buf = lzalloc(sizeof *e820buf); | ||
| 285 | + if (!e820buf) | ||
| 286 | + return -1; | ||
| 287 | + | ||
| 288 | + ireg.eax.l = 0xe820; | ||
| 289 | + ireg.edx.l = 0x534d4150; | ||
| 290 | + ireg.ebx.l = 0; | ||
| 291 | + ireg.ecx.l = sizeof(*e820buf); | ||
| 292 | + ireg.es = SEG(e820buf); | ||
| 293 | + ireg.edi.w[0] = OFFS(e820buf); | ||
| 294 | + | ||
| 295 | + do { | ||
| 296 | + __intcall(0x15, &ireg, &oreg); | ||
| 297 | + | ||
| 298 | + if ((oreg.eflags.l & EFLAGS_CF) || | ||
| 299 | + (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) | ||
| 300 | + break; | ||
| 301 | + | ||
| 302 | + start = e820buf->start; | ||
| 303 | + len = e820buf->len; | ||
| 304 | + | ||
| 305 | + if (start < 0x100000000ULL) { | ||
| 306 | + /* Don't rely on E820 being valid for low memory. Doing so | ||
| 307 | + could mean stuff like overwriting the PXE stack even when | ||
| 308 | + using "keeppxe", etc. */ | ||
| 309 | + if (start < 0x100000ULL) { | ||
| 310 | + if (len > 0x100000ULL - start) | ||
| 311 | + len -= 0x100000ULL - start; | ||
| 312 | + else | ||
| 313 | + len = 0; | ||
| 314 | + start = 0x100000ULL; | ||
| 315 | + } | ||
| 316 | + | ||
| 317 | + maxlen = 0x100000000ULL - start; | ||
| 318 | + if (len > maxlen) | ||
| 319 | + len = maxlen; | ||
| 320 | + | ||
| 321 | + if (len) { | ||
| 322 | + enum syslinux_memmap_types type; | ||
| 323 | + | ||
| 324 | + type = e820buf->type == 1 ? SMT_FREE : SMT_RESERVED; | ||
| 325 | + rv = callback(data, (addr_t) start, (addr_t) len, type); | ||
| 326 | + if (rv) | ||
| 327 | + return rv; | ||
| 328 | + memfound = 1; | ||
| 329 | + } | ||
| 330 | + } | ||
| 331 | + | ||
| 332 | + ireg.ebx.l = oreg.ebx.l; | ||
| 333 | + } while (oreg.ebx.l); | ||
| 334 | + | ||
| 335 | + lfree(e820buf); | ||
| 336 | + | ||
| 337 | + if (memfound) | ||
| 338 | + return 0; | ||
| 339 | + | ||
| 340 | + /* Next try INT 15h AX=E801h */ | ||
| 341 | + ireg.eax.w[0] = 0xe801; | ||
| 342 | + __intcall(0x15, &ireg, &oreg); | ||
| 343 | + | ||
| 344 | + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { | ||
| 345 | + rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, SMT_FREE); | ||
| 346 | + if (rv) | ||
| 347 | + return rv; | ||
| 348 | + | ||
| 349 | + if (oreg.edx.w[0]) { | ||
| 350 | + rv = callback(data, (addr_t) 16 << 20, | ||
| 351 | + oreg.edx.w[0] << 16, SMT_FREE); | ||
| 352 | + if (rv) | ||
| 353 | + return rv; | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + return 0; | ||
| 357 | + } | ||
| 358 | + | ||
| 359 | + /* Finally try INT 15h AH=88h */ | ||
| 360 | + ireg.eax.w[0] = 0x8800; | ||
| 361 | + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { | ||
| 362 | + rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, SMT_FREE); | ||
| 363 | + if (rv) | ||
| 364 | + return rv; | ||
| 365 | + } | ||
| 366 | + | ||
| 367 | + return 0; | ||
| 368 | +} | ||
| 369 | + | ||
| 370 | +static struct syslinux_memscan bios_memscan = { | ||
| 371 | + .func = bios_scan_memory, | ||
| 372 | +}; | ||
| 373 | + | ||
| 374 | void bios_init(void) | ||
| 375 | { | ||
| 376 | int i; | ||
| 377 | @@ -515,6 +638,7 @@ void bios_init(void) | ||
| 378 | |||
| 379 | /* Init the memory subsystem */ | ||
| 380 | bios_free_mem = (uint16_t *)0x413; | ||
| 381 | + syslinux_memscan_add(&bios_memscan); | ||
| 382 | mem_init(); | ||
| 383 | |||
| 384 | /* CPU-dependent initialization and related checks. */ | ||
| 385 | @@ -534,7 +658,6 @@ struct mem_ops bios_mem_ops = { | ||
| 386 | .malloc = bios_malloc, | ||
| 387 | .realloc = bios_realloc, | ||
| 388 | .free = bios_free, | ||
| 389 | - .scan_memory = bios_scan_memory, | ||
| 390 | }; | ||
| 391 | |||
| 392 | struct firmware bios_fw = { | ||
| 393 | diff --git a/efi/main.c b/efi/main.c | ||
| 394 | index 13b9403..fb8cf05 100644 | ||
| 395 | --- a/efi/main.c | ||
| 396 | +++ b/efi/main.c | ||
| 397 | @@ -296,21 +296,21 @@ int efi_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 398 | for (i = 0; i < nr_entries; bufpos += desc_sz, i++) { | ||
| 399 | EFI_MEMORY_DESCRIPTOR *m; | ||
| 400 | UINT64 region_sz; | ||
| 401 | - int valid; | ||
| 402 | + enum syslinux_memmap_types type; | ||
| 403 | |||
| 404 | m = (EFI_MEMORY_DESCRIPTOR *)bufpos; | ||
| 405 | region_sz = m->NumberOfPages * EFI_PAGE_SIZE; | ||
| 406 | |||
| 407 | switch (m->Type) { | ||
| 408 | case EfiConventionalMemory: | ||
| 409 | - valid = 1; | ||
| 410 | + type = SMT_FREE; | ||
| 411 | break; | ||
| 412 | default: | ||
| 413 | - valid = 0; | ||
| 414 | + type = SMT_RESERVED; | ||
| 415 | break; | ||
| 416 | } | ||
| 417 | |||
| 418 | - rv = callback(data, m->PhysicalStart, region_sz, valid); | ||
| 419 | + rv = callback(data, m->PhysicalStart, region_sz, type); | ||
| 420 | if (rv) | ||
| 421 | break; | ||
| 422 | } | ||
| 423 | @@ -319,11 +319,16 @@ int efi_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 424 | return rv; | ||
| 425 | } | ||
| 426 | |||
| 427 | +static struct syslinux_memscan efi_memscan = { | ||
| 428 | + .func = efi_scan_memory, | ||
| 429 | +}; | ||
| 430 | + | ||
| 431 | extern uint16_t *bios_free_mem; | ||
| 432 | void efi_init(void) | ||
| 433 | { | ||
| 434 | /* XXX timer */ | ||
| 435 | *bios_free_mem = 0; | ||
| 436 | + syslinux_memscan_add(&efi_memscan); | ||
| 437 | mem_init(); | ||
| 438 | } | ||
| 439 | |||
| 440 | @@ -1103,7 +1108,6 @@ struct mem_ops efi_mem_ops = { | ||
| 441 | .malloc = efi_malloc, | ||
| 442 | .realloc = efi_realloc, | ||
| 443 | .free = efi_free, | ||
| 444 | - .scan_memory = efi_scan_memory, | ||
| 445 | }; | ||
| 446 | |||
| 447 | struct firmware efi_fw = { | ||
| 448 | -- | ||
| 449 | 1.8.5.3 | ||
| 450 | |||
diff --git a/meta/recipes-devtools/syslinux/files/0003-PXELINUX-Add-bios-memscan-function.patch b/meta/recipes-devtools/syslinux/files/0003-PXELINUX-Add-bios-memscan-function.patch new file mode 100644 index 0000000000..70d65fd71d --- /dev/null +++ b/meta/recipes-devtools/syslinux/files/0003-PXELINUX-Add-bios-memscan-function.patch | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | Upstream-Status: Backport [d2f94e74fbd60bf491753895d2474105efb3dedf] | ||
| 2 | Signed-off-by: Jonathan Liu <net147@gmail.com> | ||
| 3 | |||
| 4 | From 5d57e8eb46f209481069d70eaa778481f6fa3edb Mon Sep 17 00:00:00 2001 | ||
| 5 | From: Matt Fleming <matt.fleming@intel.com> | ||
| 6 | Date: Wed, 17 Jul 2013 13:04:30 +0100 | ||
| 7 | Subject: [PATCH 3/4] PXELINUX: Add bios memscan function | ||
| 8 | |||
| 9 | We can mark the memory region occupied by the PXE stack as SMT_TERMINAL | ||
| 10 | provided that KeepPXE isn't set. Historically some very old | ||
| 11 | non-relocatable kernel images (memtest86+) have a load address that | ||
| 12 | falls within the PXE stack region, so we need to attempt to load into | ||
| 13 | that region if at all possible. | ||
| 14 | |||
| 15 | Signed-off-by: Matt Fleming <matt.fleming@intel.com> | ||
| 16 | --- | ||
| 17 | core/fs/pxe/bios.c | 35 +++++++++++++++++++++++++++++++++++ | ||
| 18 | 1 file changed, 35 insertions(+) | ||
| 19 | |||
| 20 | diff --git a/core/fs/pxe/bios.c b/core/fs/pxe/bios.c | ||
| 21 | index 81aa715..5f61824 100644 | ||
| 22 | --- a/core/fs/pxe/bios.c | ||
| 23 | +++ b/core/fs/pxe/bios.c | ||
| 24 | @@ -1,4 +1,5 @@ | ||
| 25 | #include <syslinux/firmware.h> | ||
| 26 | +#include <syslinux/memscan.h> | ||
| 27 | #include <core.h> | ||
| 28 | #include "pxe.h" | ||
| 29 | #include <net.h> | ||
| 30 | @@ -10,6 +11,9 @@ static uint16_t real_base_mem; /* Amount of DOS memory after freeing */ | ||
| 31 | static bool has_gpxe; | ||
| 32 | static uint32_t gpxe_funcs; | ||
| 33 | |||
| 34 | +static addr_t pxe_code_start, pxe_code_size; | ||
| 35 | +static addr_t pxe_data_start, pxe_data_size; | ||
| 36 | + | ||
| 37 | /* | ||
| 38 | * Validity check on possible !PXE structure in buf | ||
| 39 | * return 1 for success, 0 for failure. | ||
| 40 | @@ -88,6 +92,29 @@ static const struct pxenv_t *memory_scan_for_pxenv_struct(void) | ||
| 41 | return memory_scan(0x10000, is_pxenv); | ||
| 42 | } | ||
| 43 | |||
| 44 | +static int pxelinux_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 45 | +{ | ||
| 46 | + int rv = 0; | ||
| 47 | + | ||
| 48 | + /* | ||
| 49 | + * If we are planning on calling unload_pxe() and unmapping the PXE | ||
| 50 | + * region before we transfer control away from PXELINUX we can mark | ||
| 51 | + * that region as SMT_TERMINAL to indicate that the region will | ||
| 52 | + * become free at some point in the future. | ||
| 53 | + */ | ||
| 54 | + if (!KeepPXE) { | ||
| 55 | + dprintf("Marking PXE code region 0x%x - 0x%x as SMT_TERMINAL\n", | ||
| 56 | + pxe_code_start, pxe_code_start + pxe_code_size); | ||
| 57 | + rv = callback(data, pxe_code_start, pxe_code_size, SMT_TERMINAL); | ||
| 58 | + | ||
| 59 | + dprintf("Marking PXE data region 0x%x - 0x%x as SMT_TERMINAL\n", | ||
| 60 | + pxe_data_start, pxe_data_start + pxe_data_size); | ||
| 61 | + rv = callback(data, pxe_data_start, pxe_data_size, SMT_TERMINAL); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + return rv; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | /* | ||
| 68 | * Find the !PXE structure; we search for the following, in order: | ||
| 69 | * | ||
| 70 | @@ -204,6 +231,14 @@ int pxe_init(bool quiet) | ||
| 71 | printf("UNDI data segment at %04X len %04X\n", data_seg, data_len); | ||
| 72 | } | ||
| 73 | |||
| 74 | + pxe_code_start = code_seg << 4; | ||
| 75 | + pxe_code_size = code_len; | ||
| 76 | + | ||
| 77 | + pxe_data_start = data_seg << 4; | ||
| 78 | + pxe_data_size = data_len; | ||
| 79 | + | ||
| 80 | + syslinux_memscan_new(pxelinux_scan_memory); | ||
| 81 | + | ||
| 82 | code_seg = code_seg + ((code_len + 15) >> 4); | ||
| 83 | data_seg = data_seg + ((data_len + 15) >> 4); | ||
| 84 | |||
| 85 | -- | ||
| 86 | 1.8.5.3 | ||
| 87 | |||
diff --git a/meta/recipes-devtools/syslinux/files/0004-pxe-use-bios_fbm-and-real_base_mem-to-calculate-free.patch b/meta/recipes-devtools/syslinux/files/0004-pxe-use-bios_fbm-and-real_base_mem-to-calculate-free.patch new file mode 100644 index 0000000000..ee0a77237d --- /dev/null +++ b/meta/recipes-devtools/syslinux/files/0004-pxe-use-bios_fbm-and-real_base_mem-to-calculate-free.patch | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | Upstream-Status: Backport [c0ea15936de8378d1da6843d3dbddd8dddba1011] | ||
| 2 | Signed-off-by: Jonathan Liu <net147@gmail.com> | ||
| 3 | |||
| 4 | From f3347f9b09135d71a4effae1614b22dcdf16a7e2 Mon Sep 17 00:00:00 2001 | ||
| 5 | From: Matt Fleming <matt.fleming@intel.com> | ||
| 6 | Date: Wed, 24 Jul 2013 18:33:14 +0100 | ||
| 7 | Subject: [PATCH 4/4] pxe: use bios_fbm() and real_base_mem to calculate free | ||
| 8 | space | ||
| 9 | |||
| 10 | We don't need to individually add the PXE regions, we already have two | ||
| 11 | symbols that denote the memory region that will be freed when calling | ||
| 12 | unload_pxe(). | ||
| 13 | |||
| 14 | This essentially reverts commit 03dda0f1 ("pxe: mark all PXE regions as | ||
| 15 | SMT_TERMINAL"). | ||
| 16 | |||
| 17 | Signed-off-by: Matt Fleming <matt.fleming@intel.com> | ||
| 18 | |||
| 19 | Conflicts: | ||
| 20 | core/fs/pxe/bios.c | ||
| 21 | --- | ||
| 22 | core/fs/pxe/bios.c | 18 +++++++++--------- | ||
| 23 | 1 file changed, 9 insertions(+), 9 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/core/fs/pxe/bios.c b/core/fs/pxe/bios.c | ||
| 26 | index 5f61824..ffdffaf 100644 | ||
| 27 | --- a/core/fs/pxe/bios.c | ||
| 28 | +++ b/core/fs/pxe/bios.c | ||
| 29 | @@ -94,24 +94,24 @@ static const struct pxenv_t *memory_scan_for_pxenv_struct(void) | ||
| 30 | |||
| 31 | static int pxelinux_scan_memory(scan_memory_callback_t callback, void *data) | ||
| 32 | { | ||
| 33 | + addr_t start, size; | ||
| 34 | int rv = 0; | ||
| 35 | |||
| 36 | + if (KeepPXE) | ||
| 37 | + return 0; | ||
| 38 | + | ||
| 39 | /* | ||
| 40 | * If we are planning on calling unload_pxe() and unmapping the PXE | ||
| 41 | * region before we transfer control away from PXELINUX we can mark | ||
| 42 | * that region as SMT_TERMINAL to indicate that the region will | ||
| 43 | * become free at some point in the future. | ||
| 44 | */ | ||
| 45 | - if (!KeepPXE) { | ||
| 46 | - dprintf("Marking PXE code region 0x%x - 0x%x as SMT_TERMINAL\n", | ||
| 47 | - pxe_code_start, pxe_code_start + pxe_code_size); | ||
| 48 | - rv = callback(data, pxe_code_start, pxe_code_size, SMT_TERMINAL); | ||
| 49 | - | ||
| 50 | - dprintf("Marking PXE data region 0x%x - 0x%x as SMT_TERMINAL\n", | ||
| 51 | - pxe_data_start, pxe_data_start + pxe_data_size); | ||
| 52 | - rv = callback(data, pxe_data_start, pxe_data_size, SMT_TERMINAL); | ||
| 53 | - } | ||
| 54 | + start = bios_fbm() << 10; | ||
| 55 | + size = (real_base_mem - bios_fbm()) << 10; | ||
| 56 | + dprintf("Marking PXE region 0x%x - 0x%x as SMT_TERMINAL\n", | ||
| 57 | + start, start + size); | ||
| 58 | |||
| 59 | + callback(data, start, size, SMT_TERMINAL); | ||
| 60 | return rv; | ||
| 61 | } | ||
| 62 | |||
| 63 | -- | ||
| 64 | 1.8.5.3 | ||
| 65 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux_6.01.bb b/meta/recipes-devtools/syslinux/syslinux_6.01.bb index 078f8bc40b..1af6806100 100644 --- a/meta/recipes-devtools/syslinux/syslinux_6.01.bb +++ b/meta/recipes-devtools/syslinux/syslinux_6.01.bb | |||
| @@ -8,7 +8,11 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3 \ | |||
| 8 | # ldlinux.* stuff for now, so skip mtools-native | 8 | # ldlinux.* stuff for now, so skip mtools-native |
| 9 | DEPENDS = "nasm-native util-linux" | 9 | DEPENDS = "nasm-native util-linux" |
| 10 | 10 | ||
| 11 | SRC_URI = "${KERNELORG_MIRROR}/linux/utils/boot/syslinux/6.xx/syslinux-${PV}.tar.bz2" | 11 | SRC_URI = "${KERNELORG_MIRROR}/linux/utils/boot/syslinux/6.xx/syslinux-${PV}.tar.bz2 \ |
| 12 | file://0001-movebits-Add-SMT_TERMINAL-a-last-resort-region-type.patch \ | ||
| 13 | file://0002-memscan-build-a-linked-list-of-memory-scanners.patch \ | ||
| 14 | file://0003-PXELINUX-Add-bios-memscan-function.patch \ | ||
| 15 | file://0004-pxe-use-bios_fbm-and-real_base_mem-to-calculate-free.patch" | ||
| 12 | 16 | ||
| 13 | SRC_URI[md5sum] = "6945ee89e29119d459baed4937bbc534" | 17 | SRC_URI[md5sum] = "6945ee89e29119d459baed4937bbc534" |
| 14 | SRC_URI[sha256sum] = "83a04cf81e6a46b80ee5a321926eea095af3498b04317e3674b46c125c7a5b43" | 18 | SRC_URI[sha256sum] = "83a04cf81e6a46b80ee5a321926eea095af3498b04317e3674b46c125c7a5b43" |
