diff options
| author | Matt Fleming <matt.fleming@intel.com> | 2012-12-07 11:33:45 +0000 |
|---|---|---|
| committer | Matt Fleming <matt.fleming@intel.com> | 2012-12-07 11:33:45 +0000 |
| commit | 10f6cf6eef0a7da7dad1933efdbfb101155792d0 (patch) | |
| tree | d8ee3bfc6e55e739e0f135cd6d945955c670dd46 /com32/lib | |
| parent | 35928ee37da523e5f992cc462a4a4193d0bfaa4c (diff) | |
| parent | ddb10ce99c327888ade4d2ba3e4c50ad12aaa059 (diff) | |
| download | syslinux-6.00-pre3.tar.gz | |
Merge tag 'syslinux-5.00' into firmwaresyslinux-6.00-pre3
Conflicts:
Makefile
com32/elflink/ldlinux/Makefile
com32/lib/sys/module/elf_module.c
core/cleanup.c
core/comboot.inc
core/conio.c
core/fs/fs.c
core/init.c
core/mem/free.c
core/mem/malloc.c
core/timer.inc
diag/geodsp/Makefile
extlinux/main.c
mk/embedded.mk
modules/Makefile
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'com32/lib')
| -rw-r--r-- | com32/lib/asprintf.c | 5 | ||||
| -rw-r--r-- | com32/lib/bufprintf.c | 8 | ||||
| -rw-r--r-- | com32/lib/free.c | 113 | ||||
| -rw-r--r-- | com32/lib/malloc.c | 155 | ||||
| -rw-r--r-- | com32/lib/realloc.c | 98 | ||||
| -rw-r--r-- | com32/lib/sys/module/common.c | 8 | ||||
| -rw-r--r-- | com32/lib/sys/module/elf_module.c | 19 | ||||
| -rw-r--r-- | com32/lib/sys/module/exec.c | 24 | ||||
| -rw-r--r-- | com32/lib/sys/module/i386/elf_module.c | 21 | ||||
| -rw-r--r-- | com32/lib/sys/module/x86_64/elf_module.c | 21 | ||||
| -rw-r--r-- | com32/lib/sys/screensize.c | 2 | ||||
| -rw-r--r-- | com32/lib/sys/vesa/background.c | 1 | ||||
| -rw-r--r-- | com32/lib/syslinux/runimage.c | 26 | ||||
| -rw-r--r-- | com32/lib/zalloc.c | 17 |
14 files changed, 92 insertions, 426 deletions
diff --git a/com32/lib/asprintf.c b/com32/lib/asprintf.c index ef5b4b2f..eab20118 100644 --- a/com32/lib/asprintf.c +++ b/com32/lib/asprintf.c @@ -21,9 +21,10 @@ int asprintf(char **bufp, const char *format, ...) *bufp = p = malloc(bytes); if (!p) - return -1; + rv = -1; + else + rv = vsnprintf(p, bytes, format, ap); - rv = vsnprintf(p, bytes, format, ap); va_end(ap); return rv; diff --git a/com32/lib/bufprintf.c b/com32/lib/bufprintf.c index 939bcec3..d2812311 100644 --- a/com32/lib/bufprintf.c +++ b/com32/lib/bufprintf.c @@ -17,8 +17,10 @@ int vbufprintf(struct print_buf *buf, const char *format, va_list ap) char *newbuf; newbuf = realloc(buf->buf, newsize); - if (!newbuf) - return -1; + if (!newbuf) { + rv = -1; + goto bail; + } buf->buf = newbuf; buf->size = newsize; @@ -26,6 +28,8 @@ int vbufprintf(struct print_buf *buf, const char *format, va_list ap) rv = vsnprintf(buf->buf + buf->len, buf->size - buf->len, format, ap2); buf->len += rv; +bail: + va_end(ap2); return rv; } diff --git a/com32/lib/free.c b/com32/lib/free.c deleted file mode 100644 index be23865a..00000000 --- a/com32/lib/free.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * free.c - * - * Very simple linked-list based malloc()/free(). - */ - -#include <stdlib.h> -#include "malloc.h" - -static struct free_arena_header *__free_block(struct free_arena_header *ah) -{ - struct free_arena_header *pah, *nah; - - pah = ah->a.prev; - nah = ah->a.next; - if (pah->a.type == ARENA_TYPE_FREE && - (char *)pah + pah->a.size == (char *)ah) { - /* Coalesce into the previous block */ - pah->a.size += ah->a.size; - pah->a.next = nah; - nah->a.prev = pah; - -#ifdef DEBUG_MALLOC - ah->a.type = ARENA_TYPE_DEAD; -#endif - - ah = pah; - pah = ah->a.prev; - } else { - /* Need to add this block to the free chain */ - ah->a.type = ARENA_TYPE_FREE; - - ah->next_free = __malloc_head.next_free; - ah->prev_free = &__malloc_head; - __malloc_head.next_free = ah; - ah->next_free->prev_free = ah; - } - - /* In either of the previous cases, we might be able to merge - with the subsequent block... */ - if (nah->a.type == ARENA_TYPE_FREE && - (char *)ah + ah->a.size == (char *)nah) { - ah->a.size += nah->a.size; - - /* Remove the old block from the chains */ - nah->next_free->prev_free = nah->prev_free; - nah->prev_free->next_free = nah->next_free; - ah->a.next = nah->a.next; - nah->a.next->a.prev = ah; - -#ifdef DEBUG_MALLOC - nah->a.type = ARENA_TYPE_DEAD; -#endif - } - - /* Return the block that contains the called block */ - return ah; -} - -/* - * This is used to insert a block which is not previously on the - * free list. Only the a.size field of the arena header is assumed - * to be valid. - */ -void __inject_free_block(struct free_arena_header *ah) -{ - struct free_arena_header *nah; - size_t a_end = (size_t) ah + ah->a.size; - size_t n_end; - - for (nah = __malloc_head.a.next; nah->a.type != ARENA_TYPE_HEAD; - nah = nah->a.next) { - n_end = (size_t) nah + nah->a.size; - - /* Is nah entirely beyond this block? */ - if ((size_t) nah >= a_end) - break; - - /* Is this block entirely beyond nah? */ - if ((size_t) ah >= n_end) - continue; - - /* Otherwise we have some sort of overlap - reject this block */ - return; - } - - /* Now, nah should point to the successor block */ - ah->a.next = nah; - ah->a.prev = nah->a.prev; - nah->a.prev = ah; - ah->a.prev->a.next = ah; - - __free_block(ah); -} - -void free(void *ptr) -{ - struct free_arena_header *ah; - - if (!ptr) - return; - - ah = (struct free_arena_header *) - ((struct arena_header *)ptr - 1); - -#ifdef DEBUG_MALLOC - assert(ah->a.type == ARENA_TYPE_USED); -#endif - - __free_block(ah); - - /* Here we could insert code to return memory to the system. */ -} diff --git a/com32/lib/malloc.c b/com32/lib/malloc.c deleted file mode 100644 index ce35f3d1..00000000 --- a/com32/lib/malloc.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * malloc.c - * - * Very simple linked-list based malloc()/free(). - */ - -#include <stdlib.h> -#include <string.h> -#include <com32.h> -#include <syslinux/memscan.h> -#include "malloc.h" - -struct free_arena_header __malloc_head = { - { - ARENA_TYPE_HEAD, - 0, - &__malloc_head, - &__malloc_head, - }, - &__malloc_head, - &__malloc_head -}; - -/* This is extern so it can be overridden by the user application */ -extern size_t __stack_size; -extern void *__mem_end; /* Produced after argv parsing */ - -static inline size_t sp(void) -{ - size_t sp; - asm volatile ("movl %%esp,%0":"=rm" (sp)); - return sp; -} - -#define E820_MEM_MAX 0xfff00000 /* 4 GB - 1 MB */ - -static int consider_memory_area(void *dummy, addr_t start, - addr_t len, bool valid) -{ - struct free_arena_header *fp; - addr_t end; - - (void)dummy; - - if (valid && start < E820_MEM_MAX) { - if (len > E820_MEM_MAX - start) - len = E820_MEM_MAX - start; - - end = start + len; - - if (end > __com32.cs_memsize) { - if (start <= __com32.cs_memsize) { - start = __com32.cs_memsize; - len = end - start; - } - - if (len >= 2 * sizeof(struct arena_header)) { - fp = (struct free_arena_header *)start; - fp->a.size = len; - __inject_free_block(fp); - } - } - } - - return 0; -} - -static void __constructor init_memory_arena(void) -{ - struct free_arena_header *fp; - size_t start, total_space; - - start = (size_t) ARENA_ALIGN_UP(__mem_end); - total_space = sp() - start; - - if (__stack_size == 0 || __stack_size > total_space >> 1) - __stack_size = total_space >> 1; /* Half for the stack, half for the heap... */ - - if (total_space < __stack_size + 4 * sizeof(struct arena_header)) - __stack_size = total_space - 4 * sizeof(struct arena_header); - - fp = (struct free_arena_header *)start; - fp->a.size = total_space - __stack_size; - - __inject_free_block(fp); - - /* Scan the memory map to look for other suitable regions */ - if (!__com32.cs_memsize) - return; /* Old Syslinux core, can't do this... */ - - syslinux_scan_memory(consider_memory_area, NULL); -} - -static void *__malloc_from_block(struct free_arena_header *fp, size_t size) -{ - size_t fsize; - struct free_arena_header *nfp, *na; - - fsize = fp->a.size; - - /* We need the 2* to account for the larger requirements of a free block */ - if (fsize >= size + 2 * sizeof(struct arena_header)) { - /* Bigger block than required -- split block */ - nfp = (struct free_arena_header *)((char *)fp + size); - na = fp->a.next; - - nfp->a.type = ARENA_TYPE_FREE; - nfp->a.size = fsize - size; - fp->a.type = ARENA_TYPE_USED; - fp->a.size = size; - - /* Insert into all-block chain */ - nfp->a.prev = fp; - nfp->a.next = na; - na->a.prev = nfp; - fp->a.next = nfp; - - /* Replace current block on free chain */ - nfp->next_free = fp->next_free; - nfp->prev_free = fp->prev_free; - fp->next_free->prev_free = nfp; - fp->prev_free->next_free = nfp; - } else { - /* Allocate the whole block */ - fp->a.type = ARENA_TYPE_USED; - - /* Remove from free chain */ - fp->next_free->prev_free = fp->prev_free; - fp->prev_free->next_free = fp->next_free; - } - - return (void *)(&fp->a + 1); -} - -void *malloc(size_t size) -{ - struct free_arena_header *fp; - - if (size == 0) - return NULL; - - /* Add the obligatory arena header, and round up */ - size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; - - for (fp = __malloc_head.next_free; fp->a.type != ARENA_TYPE_HEAD; - fp = fp->next_free) { - if (fp->a.size >= size) { - /* Found fit -- allocate out of this block */ - return __malloc_from_block(fp, size); - } - } - - /* Nothing found... need to request a block from the kernel */ - return NULL; /* No kernel to get stuff from */ -} diff --git a/com32/lib/realloc.c b/com32/lib/realloc.c deleted file mode 100644 index 2969e313..00000000 --- a/com32/lib/realloc.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * realloc.c - */ - -#include <stdlib.h> -#include <string.h> -#include <minmax.h> - -#include "malloc.h" - -void *realloc(void *ptr, size_t size) -{ - struct free_arena_header *ah, *nah; - void *newptr; - size_t newsize, oldsize, xsize; - - if (!ptr) - return malloc(size); - - if (size == 0) { - free(ptr); - return NULL; - } - - ah = (struct free_arena_header *) - ((struct arena_header *)ptr - 1); - - /* Actual size of the old block */ - oldsize = ah->a.size; - - /* Add the obligatory arena header, and round up */ - newsize = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; - - if (oldsize >= newsize && newsize >= (oldsize >> 2) && - oldsize - newsize < 4096) { - /* This allocation is close enough already. */ - return ptr; - } else { - xsize = oldsize; - - nah = ah->a.next; - if ((char *)nah == (char *)ah + ah->a.size && - nah->a.type == ARENA_TYPE_FREE && - oldsize + nah->a.size >= newsize) { - /* Merge in subsequent free block */ - ah->a.next = nah->a.next; - ah->a.next->a.prev = ah; - nah->next_free->prev_free = nah->prev_free; - nah->prev_free->next_free = nah->next_free; - xsize = (ah->a.size += nah->a.size); - } - - if (xsize >= newsize) { - /* We can reallocate in place */ - if (xsize >= newsize + 2 * sizeof(struct arena_header)) { - /* Residual free block at end */ - nah = (struct free_arena_header *)((char *)ah + newsize); - nah->a.type = ARENA_TYPE_FREE; - nah->a.size = xsize - newsize; - ah->a.size = newsize; - - /* Insert into block list */ - nah->a.next = ah->a.next; - ah->a.next = nah; - nah->a.next->a.prev = nah; - nah->a.prev = ah; - - /* Insert into free list */ - if (newsize > oldsize) { - /* Hack: this free block is in the path of a memory object - which has already been grown at least once. As such, put - it at the *end* of the freelist instead of the beginning; - trying to save it for future realloc()s of the same block. */ - nah->prev_free = __malloc_head.prev_free; - nah->next_free = &__malloc_head; - __malloc_head.prev_free = nah; - nah->prev_free->next_free = nah; - } else { - nah->next_free = __malloc_head.next_free; - nah->prev_free = &__malloc_head; - __malloc_head.next_free = nah; - nah->next_free->prev_free = nah; - } - } - /* otherwise, use up the whole block */ - return ptr; - } else { - /* Last resort: need to allocate a new block and copy */ - oldsize -= sizeof(struct arena_header); - newptr = malloc(size); - if (newptr) { - memcpy(newptr, ptr, min(size, oldsize)); - free(ptr); - } - return newptr; - } - } -} diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index 50b8a9f6..5b0d9ee8 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -71,15 +71,19 @@ FILE *findpath(char *name) p = PATH; again: i = 0; - while (*p && *p != ':' && i < FILENAME_MAX) { + while (*p && *p != ':' && i < FILENAME_MAX - 1) { path[i++] = *p++; } if (*p == ':') p++; + /* Ensure we have a '/' separator */ + if (path[i] != '/' && i < FILENAME_MAX - 1) + path[i++] = '/'; + n = name; - while (*n && i < FILENAME_MAX) + while (*n && i < FILENAME_MAX - 1) path[i++] = *n++; path[i] = '\0'; diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c index 4ee296c4..0d27c92b 100644 --- a/com32/lib/sys/module/elf_module.c +++ b/com32/lib/sys/module/elf_module.c @@ -98,13 +98,6 @@ static int prepare_dynlinking(struct elf_module *module) { dyn_entry++; } - // Now compute the number of symbols in the symbol table - if (module->ghash_table != NULL) { - module->symtable_size = module->ghash_table[1]; - } else { - module->symtable_size = module->hash_table[1]; - } - return 0; } @@ -191,6 +184,7 @@ int module_load(struct elf_module *module) { Elf_Sym *main_sym; Elf_Ehdr elf_hdr; module_ctor_t *ctor; + struct elf_module *head = NULL; // Do not allow duplicate modules if (module_find(module->name) != NULL) { @@ -224,6 +218,8 @@ int module_load(struct elf_module *module) { CHECKED(res, prepare_dynlinking(module), error); //printf("check... 4\n"); + head = list_entry((&modules_head)->next, typeof(*head), list); + /* Find modules we need to load as dependencies */ if (module->str_table) { int i; @@ -249,7 +245,11 @@ int module_load(struct elf_module *module) { p = dep; argv[0] = p; - spawn_load(p, 1, argv); + res = spawn_load(p, 1, argv); + if (res < 0) { + printf("Failed to load %s\n", p); + goto error; + } } } @@ -294,6 +294,9 @@ int module_load(struct elf_module *module) { return 0; error: + if (head) + unload_modules_since(head->name); + // Remove the module from the module list (if applicable) list_del_init(&module->list); diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c index 29d0a2fd..559bafc7 100644 --- a/com32/lib/sys/module/exec.c +++ b/com32/lib/sys/module/exec.c @@ -194,8 +194,10 @@ int spawn_load(const char *name, int argc, char **argv) return -1; if (get_module_type(module) == EXEC_MODULE) { - if (!argc || !argv || strcmp(argv[0], name)) - return -1; + if (!argc || !argv || strcmp(argv[0], name)) { + res = -1; + goto out; + } } if (!strcmp(cur_module->name, module->name)) { @@ -218,10 +220,8 @@ int spawn_load(const char *name, int argc, char **argv) } res = module_load(module); - if (res != 0) { - _module_unload(module); - return res; - } + if (res != 0) + goto out; type = get_module_type(module); prev_module = cur_module; @@ -259,14 +259,14 @@ int spawn_load(const char *name, int argc, char **argv) cur_module = prev_module; res = module_unload(module); - if (res != 0) { - return res; - } - - return ((unsigned int)ret_val & 0xFF); + if (res != 0) + goto out; } - return 0; +out: + if (res) + _module_unload(module); + return res; } void exec_term(void) diff --git a/com32/lib/sys/module/i386/elf_module.c b/com32/lib/sys/module/i386/elf_module.c index d0eb1a8e..a3792554 100644 --- a/com32/lib/sys/module/i386/elf_module.c +++ b/com32/lib/sys/module/i386/elf_module.c @@ -30,7 +30,9 @@ int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) { int i; int res = 0; char *pht = NULL; + char *sht = NULL; Elf32_Phdr *cr_pht; + Elf32_Shdr *cr_sht; Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr Elf32_Addr max_addr = 0x00000000; // Max. ELF vaddr @@ -142,6 +144,25 @@ int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) { } } + // Get to the SHT + image_seek(elf_hdr->e_shoff, module); + + // Load the SHT + sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); + image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); + + // Setup the symtable size + for (i = 0; i < elf_hdr->e_shnum; i++) { + cr_sht = (Elf32_Shdr*)(sht + i * elf_hdr->e_shentsize); + + if (cr_sht->sh_type == SHT_DYNSYM) { + module->symtable_size = cr_sht->sh_size; + break; + } + } + + free(sht); + // Setup dynamic segment location module->dyn_table = module_get_absolute(dyn_addr, module); diff --git a/com32/lib/sys/module/x86_64/elf_module.c b/com32/lib/sys/module/x86_64/elf_module.c index 9300f989..64404a17 100644 --- a/com32/lib/sys/module/x86_64/elf_module.c +++ b/com32/lib/sys/module/x86_64/elf_module.c @@ -30,7 +30,9 @@ int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) { int i; int res = 0; char *pht = NULL; + char *sht = NULL; Elf64_Phdr *cr_pht; + Elf64_Shdr *cr_sht; Elf64_Addr min_addr = 0x0000000000000000; // Min. ELF vaddr Elf64_Addr max_addr = 0x0000000000000000; // Max. ELF vaddr @@ -142,6 +144,25 @@ int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) { } } + // Get to the SHT + image_seek(elf_hdr->e_shoff, module); + + // Load the SHT + sht = malloc(elf_hdr->e_shnum * elf_hdr->e_shentsize); + image_read(sht, elf_hdr->e_shnum * elf_hdr->e_shentsize, module); + + // Setup the symtable size + for (i = 0; i < elf_hdr->e_shnum; i++) { + cr_sht = (Elf64_Shdr*)(sht + i * elf_hdr->e_shentsize); + + if (cr_sht->sh_type == SHT_DYNSYM) { + module->symtable_size = cr_sht->sh_size; + break; + } + } + + free(sht); + // Setup dynamic segment location module->dyn_table = module_get_absolute(dyn_addr, module); diff --git a/com32/lib/sys/screensize.c b/com32/lib/sys/screensize.c index 340227cd..bcd4496c 100644 --- a/com32/lib/sys/screensize.c +++ b/com32/lib/sys/screensize.c @@ -14,7 +14,7 @@ int getscreensize(int fd, int *rows, int *cols) *rows = fp->o.rows; *cols = fp->o.cols; - if (!rows || !cols) { + if (!*rows || !*cols) { errno = ENOTTY; return -1; } diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c index 93577461..15e90895 100644 --- a/com32/lib/sys/vesa/background.c +++ b/com32/lib/sys/vesa/background.c @@ -205,7 +205,6 @@ static int read_jpeg_file(FILE * fp, uint8_t * header, int len) unsigned int bytes_per_row[1]; rv = floadfile(fp, &jpeg_file, &length_of_file, header, len); - fclose(fp); if (rv) goto err; diff --git a/com32/lib/syslinux/runimage.c b/com32/lib/syslinux/runimage.c index 4391114c..d3db75f3 100644 --- a/com32/lib/syslinux/runimage.c +++ b/com32/lib/syslinux/runimage.c @@ -42,26 +42,22 @@ extern unsigned int ipappend; void syslinux_run_kernel_image(const char *filename, const char *cmdline, uint32_t ipappend_flags, uint32_t type) { - char *bbfilename = NULL; char *bbcmdline = NULL; + size_t len; + int rv; - - bbfilename = lstrdup(filename); - if (!bbfilename) - goto fail; - - bbcmdline = lstrdup(cmdline); + /* +2 for NULL and space */ + len = strlen(filename) + strlen(cmdline) + 2; + bbcmdline = malloc(len); if (!bbcmdline) - goto fail; + return; + + rv = snprintf(bbcmdline, len, "%s %s", filename, cmdline); + if (rv == -1 || (size_t)rv >= len) + return; if (syslinux_filesystem() == SYSLINUX_FS_PXELINUX) ipappend = ipappend_flags; - execute(bbfilename, type); - -fail: - if (bbcmdline) - lfree(bbcmdline); - if (bbfilename) - lfree(bbfilename); + execute(bbcmdline, type); } diff --git a/com32/lib/zalloc.c b/com32/lib/zalloc.c deleted file mode 100644 index 0e6ed28d..00000000 --- a/com32/lib/zalloc.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * zalloc.c - */ - -#include <stdlib.h> -#include <string.h> - -void *zalloc(size_t size) -{ - void *ptr; - - ptr = malloc(size); - if (ptr) - memset(ptr, 0, size); - - return ptr; -} |
