diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-07-27 10:41:30 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-07-30 09:51:36 +0100 |
commit | 0d6f330878173c7ba45b884f3e41ce40b917c73c (patch) | |
tree | 0a887066d35d8b01914330d6ab6818fe015a5a9d /com32/lib/sys | |
parent | 0fcd9a48603497dcc2727570a50a4401bb0fd085 (diff) | |
parent | f0bbf9dd40f37f8c4870a33784996efd56955a75 (diff) | |
download | syslinux-0d6f330878173c7ba45b884f3e41ce40b917c73c.tar.gz |
Merge remote-tracking branch 'mfleming/elflink' into for-hpa/elflink/firmware
Conflicts:
Makefile
com32/elflink/ldlinux/adv.c
com32/elflink/ldlinux/kernel.c
com32/elflink/ldlinux/ldlinux.c
com32/include/bitsize/stddef.h
com32/include/bitsize/stdint.h
com32/include/stdint.h
com32/include/sys/module.h
com32/include/sys/x86_64/bitops.h
com32/include/syslinux/linux.h
com32/lib/Makefile
com32/lib/sys/ansicon_write.c
com32/lib/sys/module/elfutils.h
com32/lib/sys/vesa/efi/fill.h
com32/lib/syslinux/load_linux.c
com32/lib/syslinux/serial.c
com32/lib/syslinux/shuffle.c
core/conio.c
core/elflink/config.c
core/elflink/load_env32.c
core/graphics.c
core/include/graphics.h
core/init.c
core/pxelinux.asm
mk/elf.mk
mk/lib.mk
Diffstat (limited to 'com32/lib/sys')
-rw-r--r-- | com32/lib/sys/ansicon_write.c | 115 | ||||
-rw-r--r-- | com32/lib/sys/fileclose.c | 1 | ||||
-rw-r--r-- | com32/lib/sys/fileread.c | 1 | ||||
-rw-r--r-- | com32/lib/sys/gpxe.c | 19 | ||||
-rw-r--r-- | com32/lib/sys/module/common.c | 115 | ||||
-rw-r--r-- | com32/lib/sys/module/common.h | 14 | ||||
-rw-r--r-- | com32/lib/sys/module/elf_module.c | 169 | ||||
-rw-r--r-- | com32/lib/sys/module/elfutils.c | 4 | ||||
-rw-r--r-- | com32/lib/sys/module/elfutils.h | 72 | ||||
-rw-r--r-- | com32/lib/sys/module/exec.c | 87 | ||||
-rw-r--r-- | com32/lib/sys/module/i386/common.c | 571 | ||||
-rw-r--r-- | com32/lib/sys/module/i386/elf_module.c | 176 | ||||
-rw-r--r-- | com32/lib/sys/module/i386/elfutils.h | 64 | ||||
-rw-r--r-- | com32/lib/sys/module/shallow_module.c | 8 | ||||
-rw-r--r-- | com32/lib/sys/module/x86_64/common.c | 567 | ||||
-rw-r--r-- | com32/lib/sys/module/x86_64/elf_module.c | 190 | ||||
-rw-r--r-- | com32/lib/sys/open.c | 1 | ||||
-rw-r--r-- | com32/lib/sys/rawcon_read.c | 35 | ||||
-rw-r--r-- | com32/lib/sys/rawcon_write.c | 8 | ||||
-rw-r--r-- | com32/lib/sys/serial_write.c | 8 | ||||
-rw-r--r-- | com32/lib/sys/stdcon_write.c | 15 | ||||
-rw-r--r-- | com32/lib/sys/xserial_write.c | 8 |
22 files changed, 513 insertions, 1735 deletions
diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index a963923d..74add717 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -35,7 +35,6 @@ #include <errno.h> #include <string.h> -#include <com32.h> #include <minmax.h> #include <colortbl.h> #include <klibc/compiler.h> @@ -43,6 +42,7 @@ #include "file.h" #include "ansi.h" #include <syslinux/firmware.h> +#include "graphics.h" static void ansicon_erase(const struct term_state *, int, int, int, int); static void ansicon_write_char(int, int, uint8_t, const struct term_state *); @@ -66,53 +66,15 @@ static struct term_info ti = { .op = &__ansicon_ops }; -#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ -#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ -#define BIOS_COLS (*(uint16_t *)0x44A) -#define BIOS_PAGE (*(uint8_t *)0x462) - #define TEXT_MODE 0x0005 /* Reference counter to the screen, to keep track of if we need reinitialization. */ static int ansicon_counter = 0; -static uint16_t cursor_type; /* Saved cursor pattern */ - -void bios_set_mode(uint16_t mode) -{ - com32sys_t ireg; - - ireg.eax.w[0] = mode; - __intcall(0x22, &ireg, NULL); -} - -void bios_get_mode(int *cols, int *rows) -{ - *rows = BIOS_ROWS ? BIOS_ROWS + 1 : 25; - *cols = BIOS_COLS; -} - -void bios_get_cursor(int *x, int *y) -{ - com32sys_t ireg, oreg; - - memset(&ireg, 0, sizeof(ireg)); - - ireg.eax.b[1] = 0x03; - ireg.ebx.b[1] = BIOS_PAGE; - __intcall(0x10, &ireg, &oreg); - cursor_type = oreg.ecx.w[0]; - *x = oreg.edx.b[0]; - *y = oreg.edx.b[1]; -} - /* Common setup */ int __ansicon_open(struct file_info *fp) { - static com32sys_t ireg; /* Auto-initalized to all zero */ - com32sys_t oreg; - if (!ansicon_counter) { /* Are we disabled? */ if (syslinux_serial_console_info()->flowctl & 0x8000) { @@ -175,19 +137,6 @@ static uint8_t ansicon_attribute(const struct term_state *st) return (bg << 4) | fg; } -void bios_erase(int x0, int y0, int x1, int y1, uint8_t attribute) -{ - static com32sys_t ireg; - - ireg.eax.w[0] = 0x0600; /* Clear window */ - ireg.ebx.b[1] = attribute; - ireg.ecx.b[0] = x0; - ireg.ecx.b[1] = y0; - ireg.edx.b[0] = x1; - ireg.edx.b[1] = y1; - __intcall(0x10, &ireg, NULL); -} - /* Erase a region of the screen */ static void ansicon_erase(const struct term_state *st, int x0, int y0, int x1, int y1) @@ -198,37 +147,10 @@ static void ansicon_erase(const struct term_state *st, firmware->o_ops->erase(x0, y0, x1, y1, attribute); } -void bios_showcursor(uint16_t cursor) -{ - static com32sys_t ireg; - - ireg.eax.b[1] = 0x01; - ireg.ecx.w[0] = cursor; - __intcall(0x10, &ireg, NULL); -} - /* Show or hide the cursor */ static void ansicon_showcursor(const struct term_state *st) { - uint16_t cursor = st->cursor ? cursor_type : 0x2020; - firmware->o_ops->showcursor(cursor); -} - -void bios_set_cursor(int x, int y, bool visible) -{ - const int page = BIOS_PAGE; - struct curxy xy = BIOS_CURXY[page]; - static com32sys_t ireg; - - (void)visible; - - if (xy.x != x || xy.y != y) { - ireg.eax.b[1] = 0x02; - ireg.ebx.b[1] = page; - ireg.edx.b[1] = y; - ireg.edx.b[0] = x; - __intcall(0x10, &ireg, NULL); - } + firmware->o_ops->showcursor(st); } static void ansicon_set_cursor(int x, int y, bool visible) @@ -236,18 +158,6 @@ static void ansicon_set_cursor(int x, int y, bool visible) firmware->o_ops->set_cursor(x, y, visible); } -void bios_write_char(uint8_t ch, uint8_t attribute) -{ - static com32sys_t ireg; - - ireg.eax.b[1] = 0x09; - ireg.eax.b[0] = ch; - ireg.ebx.b[1] = BIOS_PAGE; - ireg.ebx.b[0] = attribute; - ireg.ecx.w[0] = 1; - __intcall(0x10, &ireg, NULL); -} - static void ansicon_write_char(int x, int y, uint8_t ch, const struct term_state *st) { @@ -257,18 +167,6 @@ static void ansicon_write_char(int x, int y, uint8_t ch, firmware->o_ops->write_char(ch, attribute); } -void bios_scroll_up(uint8_t cols, uint8_t rows, uint8_t attribute) -{ - static com32sys_t ireg; - - ireg.eax.w[0] = 0x0601; - ireg.ebx.b[1] = attribute; - ireg.ecx.w[0] = 0; - ireg.edx.b[1] = rows; - ireg.edx.b[0] = cols; - __intcall(0x10, &ireg, NULL); /* Scroll */ -} - static void ansicon_scroll_up(const struct term_state *st) { uint8_t rows, cols, attribute; @@ -302,15 +200,6 @@ ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count) return n; } -void bios_beep(void) -{ - static com32sys_t ireg; - - ireg.eax.w[0] = 0x0e07; - ireg.ebx.b[1] = BIOS_PAGE; - __intcall(0x10, &ireg, NULL); -} - void __ansicon_beep(void) { if (firmware->o_ops->beep) diff --git a/com32/lib/sys/fileclose.c b/com32/lib/sys/fileclose.c index 26e15082..699dbe32 100644 --- a/com32/lib/sys/fileclose.c +++ b/com32/lib/sys/fileclose.c @@ -34,6 +34,7 @@ #include <errno.h> #include <com32.h> #include <string.h> +#include <fs.h> #include "file.h" int __file_close(struct file_info *fp) diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileread.c index 7d9e1b91..26b0ceb6 100644 --- a/com32/lib/sys/fileread.c +++ b/com32/lib/sys/fileread.c @@ -34,6 +34,7 @@ #include <errno.h> #include <string.h> #include <com32.h> +#include <pmapi.h> #include <syslinux/pmapi.h> #include <minmax.h> #include "file.h" diff --git a/com32/lib/sys/gpxe.c b/com32/lib/sys/gpxe.c index d86da42a..3cc2b845 100644 --- a/com32/lib/sys/gpxe.c +++ b/com32/lib/sys/gpxe.c @@ -1,13 +1,15 @@ +#include <string.h> + #include <sys/gpxe.h> #include <syslinux/config.h> -#include <string.h> +#include <syslinux/pxe_api.h> bool is_gpxe(void) { const struct syslinux_version *sv; - com32sys_t reg; struct s_PXENV_FILE_CHECK_API *fca; bool gpxe; + int err; sv = syslinux_version(); if (sv->filesystem != SYSLINUX_FS_PXELINUX) @@ -16,23 +18,18 @@ bool is_gpxe(void) fca = lzalloc(sizeof *fca); if (!fca) return false; + fca->Size = sizeof *fca; fca->Magic = 0x91d447b2; - memset(®, 0, sizeof reg); - reg.eax.w[0] = 0x0009; - reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */ - /* reg.edi.w[0] = OFFS(fca); */ - reg.es = SEG(fca); - - __intcall(0x22, ®, ®); + err = pxe_call(PXENV_FILE_API_CHECK, fca); gpxe = true; - if (reg.eflags.l & EFLAGS_CF) + if (err) gpxe = false; /* Cannot invoke PXE stack */ - if (reg.eax.w[0] || fca->Status) + if (fca->Status) gpxe = false; /* PXE failure */ if (fca->Magic != 0xe9c17b20) diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index 1e33db8e..bc058a66 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -23,7 +23,7 @@ LIST_HEAD(modules_head); // User-space debugging routines #ifdef ELF_DEBUG -void print_elf_ehdr(Elf32_Ehdr *ehdr) { +void print_elf_ehdr(Elf_Ehdr *ehdr) { int i; fprintf(stderr, "Identification:\t"); @@ -38,18 +38,18 @@ void print_elf_ehdr(Elf32_Ehdr *ehdr) { fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff); fprintf(stderr, "SHT Offset:\t0x%08x\n", ehdr->e_shoff); //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags); - //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf32_Ehdr)); + //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf_Ehdr)); fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum, ehdr->e_shnum); } void print_elf_symbols(struct elf_module *module) { unsigned int i; - Elf32_Sym *crt_sym; + Elf_Sym *crt_sym; for (i = 1; i < module->symtable_size; i++) { - crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size); + crt_sym = (Elf_Sym*)(module->sym_table + i*module->syment_size); fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value); @@ -64,6 +64,10 @@ static FILE *findpath(char *name) char *p, *n; int i; + f = fopen(name, "rb"); /* for full path */ + if (f) + return f; + p = PATH; again: i = 0; @@ -74,15 +78,6 @@ again: if (*p == ':') p++; - if (!strcmp(path, ".")) { - if (!core_getcwd(path, sizeof(path))) { - DBG_PRINT("Could not get cwd\n"); - return NULL; - } - - i = strlen(path); - } - n = name; while (*n && i < FILENAME_MAX) path[i++] = *n++; @@ -164,7 +159,7 @@ int image_skip(size_t size, struct elf_module *module) { return 0; } -int image_seek(Elf32_Off offset, struct elf_module *module) { +int image_seek(Elf_Off offset, struct elf_module *module) { if (offset < module->u.l._cr_offset) // Cannot seek backwards return -1; @@ -226,7 +221,7 @@ struct elf_module *module_find(const char *name) { // // Performs verifications on ELF header to assure that the open file is a // valid SYSLINUX ELF module. -int check_header_common(Elf32_Ehdr *elf_hdr) { +int check_header_common(Elf_Ehdr *elf_hdr) { // Check the header magic if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 || elf_hdr->e_ident[EI_MAG1] != ELFMAG1 || @@ -237,7 +232,7 @@ int check_header_common(Elf32_Ehdr *elf_hdr) { return -1; } - if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 || + if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 && elf_hdr->e_ident[EI_CLASS] != ELFCLASS64) { DBG_PRINT("Invalid ELF class code\n"); return -1; @@ -254,15 +249,17 @@ int check_header_common(Elf32_Ehdr *elf_hdr) { return -1; } - if (elf_hdr->e_machine != EM_386 || + if (elf_hdr->e_machine != EM_386 && elf_hdr->e_machine != EM_X86_64) { DBG_PRINT("Invalid ELF architecture\n"); return -1; + } return 0; } + int enforce_dependency(struct elf_module *req, struct elf_module *dep) { struct module_dep *crt_dep; struct module_dep *new_dep; @@ -319,7 +316,7 @@ int clear_dependency(struct elf_module *req, struct elf_module *dep) { int check_symbols(struct elf_module *module) { unsigned int i; - Elf32_Sym *crt_sym = NULL, *ref_sym = NULL; + Elf_Sym *crt_sym = NULL, *ref_sym = NULL; char *crt_name; struct elf_module *crt_module; @@ -328,11 +325,11 @@ int check_symbols(struct elf_module *module) for(i = 1; i < module->symtable_size; i++) { - crt_sym = (Elf32_Sym*)(module->sym_table + i * module->syment_size); + crt_sym = symbol_get_entry(module, i); crt_name = module->str_table + crt_sym->st_name; strong_count = 0; - weak_count = 0; + weak_count = (ELF32_ST_BIND(crt_sym->st_info) == STB_WEAK); for_each_module(crt_module) { @@ -356,10 +353,17 @@ int check_symbols(struct elf_module *module) if (crt_sym->st_shndx == SHN_UNDEF) { // We have an undefined symbol + // + // We use the weak_count to differentiate + // between Syslinux-derivative-specific + // functions. For example, unload_pxe() is + // only provided by PXELINUX, so we mark it as + // __weak and replace it with a reference to + // undefined_symbol() on SYSLINUX, EXTLINUX, + // and ISOLINUX. See perform_relocations(). if (strong_count == 0 && weak_count == 0) { DBG_PRINT("Symbol %s is undefined\n", crt_name); - printf("Undef symbol FAIL: %s\n",crt_name); return -1; } } @@ -387,7 +391,7 @@ int module_unloadable(struct elf_module *module) { // Unloads the module from the system and releases all the associated memory -int module_unload(struct elf_module *module) { +int _module_unload(struct elf_module *module) { struct module_dep *crt_dep, *tmp; // Make sure nobody needs us if (!module_unloadable(module)) { @@ -416,23 +420,31 @@ int module_unload(struct elf_module *module) { return 0; } +int module_unload(struct elf_module *module) { + module_ctor_t *dtor; + + for (dtor = module->dtors; *dtor; dtor++) + (*dtor) (); + + return _module_unload(module); +} -static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { +static Elf_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { unsigned long h = elf_hash((const unsigned char*)name); - Elf32_Word *cr_word = module->hash_table; + Elf_Word *cr_word = module->hash_table; - Elf32_Word nbucket = *cr_word++; + Elf_Word nbucket = *cr_word++; cr_word++; // Skip nchain - Elf32_Word *bkt = cr_word; - Elf32_Word *chn = cr_word + nbucket; + Elf_Word *bkt = cr_word; + Elf_Word *chn = cr_word + nbucket; - Elf32_Word crt_index = bkt[h % module->hash_table[0]]; - Elf32_Sym *crt_sym; + Elf_Word crt_index = bkt[h % module->hash_table[0]]; + Elf_Sym *crt_sym; while (crt_index != STN_UNDEF) { - crt_sym = (Elf32_Sym*)(module->sym_table + crt_index*module->syment_size); + crt_sym = symbol_get_entry(module, crt_index); if (strcmp(name, module->str_table + crt_sym->st_name) == 0) return crt_sym; @@ -443,32 +455,32 @@ static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *m return NULL; } -static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { +static Elf_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { unsigned long h = elf_gnu_hash((const unsigned char*)name); // Setup code (TODO: Optimize this by computing only once) - Elf32_Word *cr_word = module->ghash_table; - Elf32_Word nbucket = *cr_word++; - Elf32_Word symbias = *cr_word++; - Elf32_Word bitmask_nwords = *cr_word++; + Elf_Word *cr_word = module->ghash_table; + Elf_Word nbucket = *cr_word++; + Elf_Word symbias = *cr_word++; + Elf_Word bitmask_nwords = *cr_word++; if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) { DBG_PRINT("Invalid GNU Hash structure\n"); return NULL; } - Elf32_Word gnu_shift = *cr_word++; + Elf_Word gnu_shift = *cr_word++; - Elf32_Addr *gnu_bitmask = (Elf32_Addr*)cr_word; + Elf_Addr *gnu_bitmask = (Elf_Addr*)cr_word; cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords; - Elf32_Word *gnu_buckets = cr_word; + Elf_Word *gnu_buckets = cr_word; cr_word += nbucket; - Elf32_Word *gnu_chain_zero = cr_word - symbias; + Elf_Word *gnu_chain_zero = cr_word - symbias; // Computations - Elf32_Word bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & + Elf_Bword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & (bitmask_nwords - 1)]; unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1); @@ -476,19 +488,18 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) { unsigned long rem; - Elf32_Word bucket; + Elf_Word bucket; rem = h % nbucket; bucket = gnu_buckets[rem]; if (bucket != 0) { - const Elf32_Word* hasharr = &gnu_chain_zero[bucket]; + const Elf_Word* hasharr = &gnu_chain_zero[bucket]; do { if (((*hasharr ^ h ) >> 1) == 0) { - Elf32_Sym *crt_sym = (Elf32_Sym*)(module->sym_table + - (hasharr - gnu_chain_zero) * module->syment_size); + Elf_Sym *crt_sym = symbol_get_entry(module, (hasharr - gnu_chain_zero)); if (strcmp(name, module->str_table + crt_sym->st_name) == 0) { return crt_sym; @@ -501,15 +512,15 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo return NULL; } -static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) +static Elf_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) { unsigned int i; - Elf32_Sym *crt_sym; + Elf_Sym *crt_sym; for (i=1; i < module->symtable_size; i++) { - crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size); + crt_sym = symbol_get_entry(module, i); if (strcmp(name, module->str_table + crt_sym->st_name) == 0) { return crt_sym; @@ -519,8 +530,8 @@ static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module return NULL; } -Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) { - Elf32_Sym *result = NULL; +Elf_Sym *module_find_symbol(const char *name, struct elf_module *module) { + Elf_Sym *result = NULL; if (module->ghash_table != NULL) result = module_find_symbol_gnu(name, module); @@ -542,10 +553,10 @@ Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) { return result; } -Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) { +Elf_Sym *global_find_symbol(const char *name, struct elf_module **module) { struct elf_module *crt_module; - Elf32_Sym *crt_sym = NULL; - Elf32_Sym *result = NULL; + Elf_Sym *crt_sym = NULL; + Elf_Sym *result = NULL; for_each_module(crt_module) { crt_sym = module_find_symbol(name, crt_module); diff --git a/com32/lib/sys/module/common.h b/com32/lib/sys/module/common.h index 928fe139..652c9735 100644 --- a/com32/lib/sys/module/common.h +++ b/com32/lib/sys/module/common.h @@ -26,6 +26,14 @@ #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) +static inline Elf_Sym *symbol_get_entry(struct elf_module *module, int entry) +{ + char *sym_table = (char *)module->sym_table; + int index = entry * module->syment_size; + + return (Elf_Sym *)(sym_table + index); +} + //#define ELF_DEBUG #ifdef ELF_DEBUG @@ -36,7 +44,7 @@ // User-space debugging routines #ifdef ELF_DEBUG -extern void print_elf_ehdr(Elf32_Ehdr *ehdr); +extern void print_elf_ehdr(Elf_Ehdr *ehdr); extern void print_elf_symbols(struct elf_module *module); #endif //ELF_DEBUG @@ -49,11 +57,11 @@ extern int image_load(struct elf_module *module); extern int image_unload(struct elf_module *module); extern int image_read(void *buff, size_t size, struct elf_module *module); extern int image_skip(size_t size, struct elf_module *module); -extern int image_seek(Elf32_Off offset, struct elf_module *module); +extern int image_seek(Elf_Off offset, struct elf_module *module); extern struct module_dep *module_dep_alloc(struct elf_module *module); -extern int check_header_common(Elf32_Ehdr *elf_hdr); +extern int check_header_common(Elf_Ehdr *elf_hdr); extern int enforce_dependency(struct elf_module *req, struct elf_module *dep); extern int clear_dependency(struct elf_module *req, struct elf_module *dep); diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c index 7d8dad42..b220e1ad 100644 --- a/com32/lib/sys/module/elf_module.c +++ b/com32/lib/sys/module/elf_module.c @@ -5,21 +5,21 @@ * Author: Stefan Bucur <stefanb@zytor.com> */ - +#include <errno.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <elf.h> #include <dprintf.h> +#include <core.h> #include <linux/list.h> #include <sys/module.h> +#include <sys/exec.h> #include "elfutils.h" #include "common.h" -#define MAX_NR_DEPS 64 - static int check_header(Elf32_Ehdr *elf_hdr) { int res; @@ -50,7 +50,7 @@ static int check_header(Elf32_Ehdr *elf_hdr) { static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) { int i; int res = 0; - void *pht = NULL; + char *pht = NULL; Elf32_Phdr *cr_pht; Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr @@ -136,8 +136,8 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) { // headers Elf32_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; - if (image_read(module_get_absolute(cr_pht->p_vaddr, module) + aux_off, - cr_pht->p_filesz - aux_off, module) < 0) { + if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, + cr_pht->p_filesz - aux_off, module) < 0) { res = -1; goto out; } @@ -180,9 +180,6 @@ out: return res; } -static int nr_needed; -static Elf32_Word needed[MAX_NR_DEPS];; - static int prepare_dynlinking(struct elf_module *module) { Elf32_Dyn *dyn_entry = module->dyn_table; @@ -195,8 +192,8 @@ static int prepare_dynlinking(struct elf_module *module) { * are then inform the user that we ran out of * space. */ - if (nr_needed < MAX_NR_DEPS) - needed[nr_needed++] = dyn_entry->d_un.d_ptr; + if (module->nr_needed < MAX_NR_DEPS) + module->needed[module->nr_needed++] = dyn_entry->d_un.d_ptr; else { printf("Too many dependencies!\n"); return -1; @@ -242,6 +239,11 @@ static int prepare_dynlinking(struct elf_module *module) { return 0; } +void undefined_symbol(void) +{ + printf("Error: An undefined symbol was referenced\n"); + kaboom(); +} static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { Elf32_Word *dest = module_get_absolute(rel->r_offset, module); @@ -259,8 +261,7 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { // Find out details about the symbol // The symbol reference - Elf32_Sym *sym_ref = - (Elf32_Sym*)(module->sym_table + sym * module->syment_size); + Elf32_Sym *sym_ref = symbol_get_entry(module, sym); // The symbol definition sym_def = @@ -268,11 +269,16 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { &sym_module); if (sym_def == NULL) { - // This should never happen DBG_PRINT("Cannot perform relocation for symbol %s\n", module->str_table + sym_ref->st_name); - return -1; + if (ELF32_ST_BIND(sym_ref->st_info) != STB_WEAK) + return -1; + + // This must be a derivative-specific + // function. We're OK as long as we never + // execute the function. + sym_def = global_find_symbol("undefined_symbol", &sym_module); } // Compute the absolute symbol virtual address @@ -321,9 +327,9 @@ static int resolve_symbols(struct elf_module *module) { int res; Elf32_Word plt_rel_size = 0; - void *plt_rel = NULL; + char *plt_rel = NULL; - void *rel = NULL; + char *rel = NULL; Elf32_Word rel_size = 0; Elf32_Word rel_entry = 0; @@ -398,32 +404,70 @@ static int resolve_symbols(struct elf_module *module) { return 0; } +static int extract_operations(struct elf_module *module) { + Elf32_Sym *ctors_start, *ctors_end; + Elf32_Sym *dtors_start, *dtors_end; + module_ctor_t *ctors = NULL; + module_ctor_t *dtors = NULL; + ctors_start = module_find_symbol("__ctors_start", module); + ctors_end = module_find_symbol("__ctors_end", module); -static int extract_operations(struct elf_module *module) { - Elf32_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module); - Elf32_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module); - Elf32_Sym *main_sym = module_find_symbol("main", module); - - if (init_sym) { - module->init_func = (module_init_t*)module_get_absolute( - init_sym->st_value, module); - if (*(module->init_func) == NULL) { - module->init_func = NULL; + if (ctors_start && ctors_end) { + module_ctor_t *start, *end; + int nr_ctors = 0; + int i, size; + + start = module_get_absolute(ctors_start->st_value, module); + end = module_get_absolute(ctors_end->st_value, module); + + nr_ctors = end - start; + + size = nr_ctors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + ctors = malloc(size); + if (!ctors) { + printf("Unable to alloc memory for ctors\n"); + return -1; } + + memset(ctors, 0, size); + for (i = 0; i < nr_ctors; i++) + ctors[i] = start[i]; + + module->ctors = ctors; } - if (exit_sym) { - module->exit_func = (module_exit_t*)module_get_absolute( - exit_sym->st_value, module); - if (*(module->exit_func) == NULL) { - module->exit_func = NULL; + dtors_start = module_find_symbol("__dtors_start", module); + dtors_end = module_find_symbol("__dtors_end", module); + + if (dtors_start && dtors_end) { + module_ctor_t *start, *end; + int nr_dtors = 0; + int i, size; + + start = module_get_absolute(dtors_start->st_value, module); + end = module_get_absolute(dtors_end->st_value, module); + + nr_dtors = end - start; + + size = nr_dtors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + dtors = malloc(size); + if (!dtors) { + printf("Unable to alloc memory for dtors\n"); + free(ctors); + return -1; } - } - if (main_sym) - module->main_func = - module_get_absolute(main_sym->st_value, module); + memset(dtors, 0, size); + for (i = 0; i < nr_dtors; i++) + dtors[i] = start[i]; + + module->dtors = dtors; + } return 0; } @@ -431,12 +475,14 @@ static int extract_operations(struct elf_module *module) { // Loads the module into the system int module_load(struct elf_module *module) { int res; + Elf32_Sym *main_sym; Elf32_Ehdr elf_hdr; + module_ctor_t *ctor; // Do not allow duplicate modules if (module_find(module->name) != NULL) { DBG_PRINT("Module %s is already loaded.\n", module->name); - return -1; + return EEXIST; } // Get a mapping/copy of the ELF file in memory @@ -462,42 +508,35 @@ int module_load(struct elf_module *module) { CHECKED(res, load_segments(module, &elf_hdr), error); //printf("bleah... 3\n"); // Obtain dynamic linking information - nr_needed = 0; CHECKED(res, prepare_dynlinking(module), error); //printf("check... 4\n"); - // - //dump_elf_module(module); /* Find modules we need to load as dependencies */ if (module->str_table) { - int i, n; + int i; /* - * nr_needed can be modified by recursive calls to - * module_load() so keep a local copy on the stack. + * Note that we have to load the dependencies in + * reverse order. */ - n = nr_needed; - for (i = 0; i < n; i++) { - size_t len, j; + for (i = module->nr_needed - 1; i >= 0; i--) { char *dep, *p; + char *argv[2] = { NULL, NULL }; - dep = module->str_table + needed[i]; + dep = module->str_table + module->needed[i]; /* strip everything but the last component */ - j = len = strlen(dep); - if (!len) + if (!strlen(dep)) continue; - p = dep + len - 1; - while (j > 0 && *p && *p != '/') { - p--; - j--; - } + if (strchr(dep, '/')) { + p = strrchr(dep, '/'); + p++; + } else + p = dep; - if (*p++ == '/') { - char argv[2] = { p, NULL }; - spawn_load(p, 1, argv); - } + argv[0] = p; + spawn_load(p, 1, argv); } } @@ -505,8 +544,11 @@ int module_load(struct elf_module *module) { CHECKED(res, check_symbols(module), error); //printf("check... 5\n"); - // Obtain constructors and destructors - CHECKED(res, extract_operations(module), error); + main_sym = module_find_symbol("main", module); + if (main_sym) + module->main_func = + module_get_absolute(main_sym->st_value, module); + //printf("check... 6\n"); // Add the module at the beginning of the module list @@ -515,6 +557,9 @@ int module_load(struct elf_module *module) { // Perform the relocations resolve_symbols(module); + // Obtain constructors and destructors + CHECKED(res, extract_operations(module), error); + //dprintf("module->symtable_size = %d\n", module->symtable_size); //print_elf_symbols(module); @@ -529,6 +574,10 @@ int module_load(struct elf_module *module) { (module->init_func == NULL) ? NULL : *(module->init_func), (module->exit_func == NULL) ? NULL : *(module->exit_func)); */ + + for (ctor = module->ctors; *ctor; ctor++) + (*ctor) (); + return 0; error: diff --git a/com32/lib/sys/module/elfutils.c b/com32/lib/sys/module/elfutils.c index 64be0770..b7d760b4 100644 --- a/com32/lib/sys/module/elfutils.c +++ b/com32/lib/sys/module/elfutils.c @@ -37,7 +37,7 @@ struct memalign_info { }; int elf_malloc(void **memptr, size_t alignment, size_t size) { - void *start_addr = NULL; + char *start_addr = NULL; struct memalign_info *info; if ((alignment & (alignment - 1)) != 0) @@ -63,7 +63,7 @@ int elf_malloc(void **memptr, size_t alignment, size_t size) { return 0; } -void elf_free(void *memptr) { +void elf_free(char *memptr) { struct memalign_info *info = (struct memalign_info*)(memptr - sizeof(struct memalign_info)); diff --git a/com32/lib/sys/module/elfutils.h b/com32/lib/sys/module/elfutils.h index b6750ae7..91bdcb3f 100644 --- a/com32/lib/sys/module/elfutils.h +++ b/com32/lib/sys/module/elfutils.h @@ -1,7 +1,65 @@ -#if __SIZEOF_POINTER__ == 4 -#include <i386/elfutils.h> -#elif __SIZEOF_POINTER__ == 8 -#include <x86_64/elfutils.h> -#else -#error "unsupported architecture" -#endif +#ifndef ELF_UTILS_H_ +#define ELF_UTILS_H_ + +#include <elf.h> +#include <stdlib.h> +#include <sys/module.h> + +/** + * elf_get_header - Returns a pointer to the ELF header structure. + * @elf_image: pointer to the ELF file image in memory + */ +static inline Elf_Ehdr *elf_get_header(void *elf_image) { + return (Elf_Ehdr*)elf_image; +} + +/** + * elf_get_pht - Returns a pointer to the first entry in the PHT. + * @elf_image: pointer to the ELF file image in memory + */ +static inline Elf_Phdr *elf_get_pht(void *elf_image) { + Elf_Ehdr *elf_hdr = elf_get_header(elf_image); + + return (Elf_Phdr*)((Elf_Off)elf_hdr + elf_hdr->e_phoff); +} + +// +/** + * elf_get_ph - Returns the element with the given index in the PTH + * @elf_image: pointer to the ELF file image in memory + * @index: the index of the PHT entry to look for + */ +static inline Elf_Phdr *elf_get_ph(void *elf_image, int index) { + Elf_Phdr *elf_pht = elf_get_pht(elf_image); + Elf_Ehdr *elf_hdr = elf_get_header(elf_image); + + return (Elf_Phdr*)((Elf_Off)elf_pht + index * elf_hdr->e_phentsize); +} + +/** + * elf_hash - Returns the index in a SysV hash table for the symbol name. + * @name: the name of the symbol to look for + */ +extern unsigned long elf_hash(const unsigned char *name); + +/** + * elf_gnu_hash - Returns the index in a GNU hash table for the symbol name. + * @name: the name of the symbol to look for + */ +extern unsigned long elf_gnu_hash(const unsigned char *name); + +/** + * elf_malloc - Allocates memory to be used by ELF module contents. + * @memptr: pointer to a variable to hold the address of the allocated block. + * @alignment: alignment constraints of the block + * @size: the required size of the block + */ +extern int elf_malloc(void **memptr, size_t alignment, size_t size); + +/** + * elf_free - Releases memory previously allocated by elf_malloc. + * @memptr: the address of the allocated block + */ +extern void elf_free(char *memptr); + +#endif /*ELF_UTILS_H_*/ diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c index 71d31929..29d0a2fd 100644 --- a/com32/lib/sys/module/exec.c +++ b/com32/lib/sys/module/exec.c @@ -47,64 +47,7 @@ int exec_init(void) int get_module_type(struct elf_module *module) { if(module->main_func) return EXEC_MODULE; - else if(module->init_func) return LIB_MODULE; - return UNKNOWN_MODULE; -} - -int load_library(const char *name) -{ - int res; - struct elf_module *module = module_alloc(name); - - if (module == NULL) - return -1; - - res = module_load(module); - if (res != 0) { - module_unload(module); - return res; - } - - if (module->main_func != NULL) { - DBG_PRINT("Cannot load executable module as library.\n"); - module_unload(module); - return -1; - } - - if (module->init_func != NULL) { - res = (*(module->init_func))(); - if (res) - DBG_PRINT("Initialization error! function returned: %d\n", res); - } else { - DBG_PRINT("No initialization function present.\n"); - } - - if (res != 0) { - module_unload(module); - return res; - } - - return 0; -} - -int unload_library(const char *name) -{ - int res; - struct elf_module *module = module_find(name); - - if (module == NULL) - return -1; - - if (!module_unloadable(module)) { - return -1; - } - - if (module->exit_func != NULL) { - (*(module->exit_func))(); - } - - res = module_unload(module); - return res; + return LIB_MODULE; } jmp_buf __process_exit_jmp; @@ -243,7 +186,6 @@ int spawn_load(const char *name, int argc, char **argv) //malloc_tag_t prev_mem_tag; struct elf_module *module = module_alloc(name); struct elf_module *prev_module; - int type; dprintf("enter: name = %s", name); @@ -277,7 +219,7 @@ int spawn_load(const char *name, int argc, char **argv) res = module_load(module); if (res != 0) { - module_unload(module); + _module_unload(module); return res; } @@ -288,23 +230,7 @@ int spawn_load(const char *name, int argc, char **argv) dprintf("type = %d, prev = %s, cur = %s", type, prev_module->name, cur_module->name); - if(type==LIB_MODULE) - { - if (module->init_func != NULL) { - res = (*(module->init_func))(); - DBG_PRINT("Initialization function returned: %d\n", res); - } else { - DBG_PRINT("No initialization function present.\n"); - } - - if (res != 0) { - cur_module = prev_module; - module_unload(module); - return res; - } - return 0; - } - else if(type==EXEC_MODULE) + if(type==EXEC_MODULE) { previous = __syslinux_current; //prev_mem_tag = __mem_get_tag_global(); @@ -323,7 +249,6 @@ int spawn_load(const char *name, int argc, char **argv) else exit((module->main_func)(argc, argv)); /* Actually run! */ - // Clean up the allocation context //__free_tagged(module); // Restore the allocation context @@ -340,10 +265,8 @@ int spawn_load(const char *name, int argc, char **argv) return ((unsigned int)ret_val & 0xFF); } - /* - module_unload(module); - return -1; - */ + + return 0; } void exec_term(void) diff --git a/com32/lib/sys/module/i386/common.c b/com32/lib/sys/module/i386/common.c deleted file mode 100644 index 41e71e83..00000000 --- a/com32/lib/sys/module/i386/common.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * common.c - * - * Created on: Aug 11, 2008 - * Author: Stefan Bucur <stefanb@zytor.com> - */ - -#include <stdio.h> -#include <elf.h> -#include <string.h> -#include <fs.h> - -#include <linux/list.h> -#include <sys/module.h> - -#include "elfutils.h" -#include "common.h" - -/** - * The one and only list of loaded modules - */ -LIST_HEAD(modules_head); - -// User-space debugging routines -#ifdef ELF_DEBUG -void print_elf_ehdr(Elf32_Ehdr *ehdr) { - int i; - - fprintf(stderr, "Identification:\t"); - for (i=0; i < EI_NIDENT; i++) { - printf("%d ", ehdr->e_ident[i]); - } - fprintf(stderr, "\n"); - fprintf(stderr, "Type:\t\t%u\n", ehdr->e_type); - fprintf(stderr, "Machine:\t%u\n", ehdr->e_machine); - fprintf(stderr, "Version:\t%u\n", ehdr->e_version); - fprintf(stderr, "Entry:\t\t0x%08x\n", ehdr->e_entry); - fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff); - fprintf(stderr, "SHT Offset:\t0x%08x\n", ehdr->e_shoff); - //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags); - //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf32_Ehdr)); - fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum, - ehdr->e_shnum); -} - -void print_elf_symbols(struct elf_module *module) { - unsigned int i; - Elf32_Sym *crt_sym; - - for (i = 1; i < module->symtable_size; i++) - { - crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size); - - fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value); - - } -} -#endif //ELF_DEBUG - -static FILE *findpath(char *name) -{ - char path[FILENAME_MAX]; - FILE *f; - char *p, *n; - int i; - - p = PATH; -again: - memset(path, '\0', sizeof(path)); - i = 0; - while (*p && *p != ':' && i < FILENAME_MAX) { - path[i++] = *p++; - } - //path[i] = '\0'; // without null the strcmp will fail - - if (*p == ':') - p++; - - if (!strcmp(path, ".")) { - if (!core_getcwd(path, sizeof(path))) { - DBG_PRINT("Could not get cwd\n"); - return NULL; - } - i = strlen(path); - } - - n = name; - while (*n && i < FILENAME_MAX) - path[i++] = *n++; - path[i] = '\0'; - - f = fopen(path, "rb"); - if (f) - return f; - - if (p >= PATH && p < PATH + strlen(PATH)) - goto again; - - return NULL; -} - -/* - * Image files manipulation routines - */ - -int image_load(struct elf_module *module) -{ - module->u.l._file = findpath(module->name); - - if (module->u.l._file == NULL) { - DBG_PRINT("Could not open object file '%s'\n", module->name); - goto error; - } - - module->u.l._cr_offset = 0; - - return 0; - -error: - if (module->u.l._file != NULL) { - fclose(module->u.l._file); - module->u.l._file = NULL; - } - - return -1; -} - - -int image_unload(struct elf_module *module) { - if (module->u.l._file != NULL) { - fclose(module->u.l._file); - module->u.l._file = NULL; - - } - module->u.l._cr_offset = 0; - - return 0; -} - -int image_read(void *buff, size_t size, struct elf_module *module) { - size_t result = fread(buff, size, 1, module->u.l._file); - - if (result < 1) - return -1; - - module->u.l._cr_offset += size; - return 0; -} - -int image_skip(size_t size, struct elf_module *module) { - void *skip_buff = NULL; - size_t result; - - if (size == 0) - return 0; - - skip_buff = malloc(size); - result = fread(skip_buff, size, 1, module->u.l._file); - free(skip_buff); - - if (result < 1) - return -1; - - module->u.l._cr_offset += size; - return 0; -} - -int image_seek(Elf32_Off offset, struct elf_module *module) { - if (offset < module->u.l._cr_offset) // Cannot seek backwards - return -1; - - return image_skip(offset - module->u.l._cr_offset, module); -} - - -// Initialization of the module subsystem -int modules_init(void) { - return 0; -} - -// Termination of the module subsystem -void modules_term(void) { - -} - -// Allocates the structure for a new module -struct elf_module *module_alloc(const char *name) { - struct elf_module *result = malloc(sizeof(struct elf_module)); - - memset(result, 0, sizeof(struct elf_module)); - - INIT_LIST_HEAD(&result->list); - INIT_LIST_HEAD(&result->required); - INIT_LIST_HEAD(&result->dependants); - - strncpy(result->name, name, MODULE_NAME_SIZE); - - return result; -} - -struct module_dep *module_dep_alloc(struct elf_module *module) { - struct module_dep *result = malloc(sizeof(struct module_dep)); - - INIT_LIST_HEAD (&result->list); - - result->module = module; - - return result; -} - -struct elf_module *module_find(const char *name) { - struct elf_module *cr_module; - - for_each_module(cr_module) { - if (strcmp(cr_module->name, name) == 0) - return cr_module; - } - - return NULL; -} - - -// Performs verifications on ELF header to assure that the open file is a -// valid SYSLINUX ELF module. -int check_header_common(Elf32_Ehdr *elf_hdr) { - // Check the header magic - if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 || - elf_hdr->e_ident[EI_MAG1] != ELFMAG1 || - elf_hdr->e_ident[EI_MAG2] != ELFMAG2 || - elf_hdr->e_ident[EI_MAG3] != ELFMAG3) { - - DBG_PRINT("The file is not an ELF object\n"); - return -1; - } - - if (elf_hdr->e_ident[EI_CLASS] != MODULE_ELF_CLASS) { - DBG_PRINT("Invalid ELF class code\n"); - return -1; - } - - if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) { - DBG_PRINT("Invalid ELF data encoding\n"); - return -1; - } - - if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION || - elf_hdr->e_version != MODULE_ELF_VERSION) { - DBG_PRINT("Invalid ELF file version\n"); - return -1; - } - - if (elf_hdr->e_machine != MODULE_ELF_MACHINE) { - DBG_PRINT("Invalid ELF architecture\n"); - return -1; - } - - return 0; -} - - -int enforce_dependency(struct elf_module *req, struct elf_module *dep) { - struct module_dep *crt_dep; - struct module_dep *new_dep; - - list_for_each_entry(crt_dep, &req->dependants, list) { - if (crt_dep->module == dep) { - // The dependency is already enforced - return 0; - } - } - - new_dep = module_dep_alloc(req); - list_add(&new_dep->list, &dep->required); - - new_dep = module_dep_alloc(dep); - list_add(&new_dep->list, &req->dependants); - - return 0; -} - -int clear_dependency(struct elf_module *req, struct elf_module *dep) { - struct module_dep *crt_dep = NULL; - int found = 0; - - list_for_each_entry(crt_dep, &req->dependants, list) { - if (crt_dep->module == dep) { - found = 1; - break; - } - } - - if (found) { - list_del(&crt_dep->list); - free(crt_dep); - } - - found = 0; - - list_for_each_entry(crt_dep, &dep->required, list) { - if (crt_dep->module == req) { - found = 1; - break; - } - } - - if (found) { - list_del(&crt_dep->list); - free(crt_dep); - } - - return 0; -} - -int check_symbols(struct elf_module *module) -{ - unsigned int i; - Elf32_Sym *crt_sym = NULL, *ref_sym = NULL; - char *crt_name; - struct elf_module *crt_module; - - int strong_count; - int weak_count; - - for(i = 1; i < module->symtable_size; i++) - { - crt_sym = (Elf32_Sym*)(module->sym_table + i * module->syment_size); - crt_name = module->str_table + crt_sym->st_name; - - strong_count = 0; - weak_count = 0; - - for_each_module(crt_module) - { - ref_sym = module_find_symbol(crt_name, crt_module); - - // If we found a definition for our symbol... - if (ref_sym != NULL && ref_sym->st_shndx != SHN_UNDEF) - { - switch (ELF32_ST_BIND(ref_sym->st_info)) - { - case STB_GLOBAL: - strong_count++; - break; - case STB_WEAK: - weak_count++; - break; - } - } - } - - if (crt_sym->st_shndx == SHN_UNDEF) - { - // We have an undefined symbol - if (strong_count == 0 && weak_count == 0) - { - DBG_PRINT("Symbol %s is undefined\n", crt_name); - //printf("Undef symbol FAIL: %s\n",crt_name); - return -1; - } - } - else - { - if (strong_count > 0 && ELF32_ST_BIND(ref_sym->st_info) == STB_GLOBAL) - { - // It's not an error - at relocation, the most recent symbol - // will be considered - DBG_PRINT("Info: Symbol %s is defined more than once\n", crt_name); - } - } - //printf("symbol %s laoded from %d\n",crt_name,crt_sym->st_value); - } - - return 0; -} - -int module_unloadable(struct elf_module *module) { - if (!list_empty(&module->dependants)) - return 0; - - return 1; -} - - -// Unloads the module from the system and releases all the associated memory -int module_unload(struct elf_module *module) { - struct module_dep *crt_dep, *tmp; - // Make sure nobody needs us - if (!module_unloadable(module)) { - DBG_PRINT("Module is required by other modules.\n"); - return -1; - } - - // Remove any dependency information - list_for_each_entry_safe(crt_dep, tmp, &module->required, list) { - clear_dependency(crt_dep->module, module); - } - - // Remove the module from the module list - list_del_init(&module->list); - - // Release the loaded segments or sections - if (module->module_addr != NULL) { - elf_free(module->module_addr); - - DBG_PRINT("%s MODULE %s UNLOADED\n", module->shallow ? "SHALLOW" : "", - module->name); - } - // Release the module structure - free(module); - - return 0; -} - - -static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { - unsigned long h = elf_hash((const unsigned char*)name); - Elf32_Word *cr_word = module->hash_table; - - Elf32_Word nbucket = *cr_word++; - cr_word++; // Skip nchain - - Elf32_Word *bkt = cr_word; - Elf32_Word *chn = cr_word + nbucket; - - Elf32_Word crt_index = bkt[h % module->hash_table[0]]; - Elf32_Sym *crt_sym; - - - while (crt_index != STN_UNDEF) { - crt_sym = (Elf32_Sym*)(module->sym_table + crt_index*module->syment_size); - - if (strcmp(name, module->str_table + crt_sym->st_name) == 0) - return crt_sym; - - crt_index = chn[crt_index]; - } - - return NULL; -} - -static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { - unsigned long h = elf_gnu_hash((const unsigned char*)name); - - // Setup code (TODO: Optimize this by computing only once) - Elf32_Word *cr_word = module->ghash_table; - Elf32_Word nbucket = *cr_word++; - Elf32_Word symbias = *cr_word++; - Elf32_Word bitmask_nwords = *cr_word++; - - - if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) { - DBG_PRINT("Invalid GNU Hash structure\n"); - return NULL; - } - - Elf32_Word gnu_shift = *cr_word++; - - Elf32_Addr *gnu_bitmask = (Elf32_Addr*)cr_word; - cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords; - - Elf32_Word *gnu_buckets = cr_word; - cr_word += nbucket; - - Elf32_Word *gnu_chain_zero = cr_word - symbias; - - // Computations - Elf32_Word bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & - (bitmask_nwords - 1)]; - - unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1); - unsigned int hashbit2 = (h >> gnu_shift) & (MODULE_ELF_CLASS_SIZE - 1); - - if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) { - unsigned long rem; - Elf32_Word bucket; - - rem = h % nbucket; - - bucket = gnu_buckets[rem]; - - if (bucket != 0) { - const Elf32_Word* hasharr = &gnu_chain_zero[bucket]; - - do { - if (((*hasharr ^ h ) >> 1) == 0) { - Elf32_Sym *crt_sym = (Elf32_Sym*)(module->sym_table + - (hasharr - gnu_chain_zero) * module->syment_size); - - if (strcmp(name, module->str_table + crt_sym->st_name) == 0) { - return crt_sym; - } - } - } while ((*hasharr++ & 1u) == 0); - } - } - - return NULL; -} - -static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) -{ - - unsigned int i; - Elf32_Sym *crt_sym; - - for (i=1; i < module->symtable_size; i++) - { - crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size); - if (strcmp(name, module->str_table + crt_sym->st_name) == 0) - { - return crt_sym; - } - } - - return NULL; -} - -Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) { - Elf32_Sym *result = NULL; - - - if (module->ghash_table != NULL) - result = module_find_symbol_gnu(name, module); - - if (result == NULL) - { - if (module->hash_table != NULL) - { - //printf("Attempting SYSV Symbol search\n"); - result = module_find_symbol_sysv(name, module); - } - else - { - //printf("Attempting Iterative Symbol search\n"); - result = module_find_symbol_iterate(name, module); - } - } - - return result; -} - -Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) { - struct elf_module *crt_module; - Elf32_Sym *crt_sym = NULL; - Elf32_Sym *result = NULL; - - for_each_module(crt_module) { - crt_sym = module_find_symbol(name, crt_module); - - if (crt_sym != NULL && crt_sym->st_shndx != SHN_UNDEF) { - switch (ELF32_ST_BIND(crt_sym->st_info)) { - case STB_GLOBAL: - if (module != NULL) { - *module = crt_module; - } - return crt_sym; - case STB_WEAK: - // Consider only the first weak symbol - if (result == NULL) { - if (module != NULL) { - *module = crt_module; - } - result = crt_sym; - } - break; - } - } - } - - return result; -} diff --git a/com32/lib/sys/module/i386/elf_module.c b/com32/lib/sys/module/i386/elf_module.c index 864344a7..f4a8618a 100644 --- a/com32/lib/sys/module/i386/elf_module.c +++ b/com32/lib/sys/module/i386/elf_module.c @@ -5,20 +5,20 @@ * Author: Stefan Bucur <stefanb@zytor.com> */ - +#include <errno.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <elf.h> #include <dprintf.h> +#include <core.h> #include <linux/list.h> #include <sys/module.h> +#include <sys/exec.h> #include "elfutils.h" -#include "common.h" - -#define MAX_NR_DEPS 64 +#include "../common.h" static int check_header(Elf32_Ehdr *elf_hdr) { int res; @@ -50,7 +50,7 @@ static int check_header(Elf32_Ehdr *elf_hdr) { static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) { int i; int res = 0; - void *pht = NULL; + char *pht = NULL; Elf32_Phdr *cr_pht; Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr @@ -136,8 +136,8 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) { // headers Elf32_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; - if (image_read(module_get_absolute(cr_pht->p_vaddr, module) + aux_off, - cr_pht->p_filesz - aux_off, module) < 0) { + if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, + cr_pht->p_filesz - aux_off, module) < 0) { res = -1; goto out; } @@ -180,9 +180,6 @@ out: return res; } -static int nr_needed; -static Elf32_Word needed[MAX_NR_DEPS];; - static int prepare_dynlinking(struct elf_module *module) { Elf32_Dyn *dyn_entry = module->dyn_table; @@ -195,8 +192,8 @@ static int prepare_dynlinking(struct elf_module *module) { * are then inform the user that we ran out of * space. */ - if (nr_needed < MAX_NR_DEPS) - needed[nr_needed++] = dyn_entry->d_un.d_ptr; + if (module->nr_needed < MAX_NR_DEPS) + module->needed[module->nr_needed++] = dyn_entry->d_un.d_ptr; else { printf("Too many dependencies!\n"); return -1; @@ -242,6 +239,11 @@ static int prepare_dynlinking(struct elf_module *module) { return 0; } +void undefined_symbol(void) +{ + printf("Error: An undefined symbol was referenced\n"); + kaboom(); +} static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { Elf32_Word *dest = module_get_absolute(rel->r_offset, module); @@ -259,8 +261,7 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { // Find out details about the symbol // The symbol reference - Elf32_Sym *sym_ref = - (Elf32_Sym*)(module->sym_table + sym * module->syment_size); + Elf32_Sym *sym_ref = symbol_get_entry(module, sym); // The symbol definition sym_def = @@ -268,15 +269,16 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { &sym_module); if (sym_def == NULL) { - // This should never happen DBG_PRINT("Cannot perform relocation for symbol %s\n", module->str_table + sym_ref->st_name); - /* - printf("Cannot perform relocation for symbol %s\n", - module->str_table + sym_ref->st_name); - */ - return -1; + if (ELF32_ST_BIND(sym_ref->st_info) != STB_WEAK) + return -1; + + // This must be a derivative-specific + // function. We're OK as long as we never + // execute the function. + sym_def = global_find_symbol("undefined_symbol", &sym_module); } // Compute the absolute symbol virtual address @@ -325,9 +327,9 @@ static int resolve_symbols(struct elf_module *module) { int res; Elf32_Word plt_rel_size = 0; - void *plt_rel = NULL; + char *plt_rel = NULL; - void *rel = NULL; + char *rel = NULL; Elf32_Word rel_size = 0; Elf32_Word rel_entry = 0; @@ -346,7 +348,6 @@ static int resolve_symbols(struct elf_module *module) { DBG_PRINT("Unsupported PLT relocation\n"); return -1; } - //break; // mouli: wasn't there before case DT_JMPREL: plt_rel = module_get_absolute(dyn_entry->d_un.d_ptr, module); break; @@ -403,32 +404,70 @@ static int resolve_symbols(struct elf_module *module) { return 0; } +static int extract_operations(struct elf_module *module) { + Elf32_Sym *ctors_start, *ctors_end; + Elf32_Sym *dtors_start, *dtors_end; + module_ctor_t *ctors = NULL; + module_ctor_t *dtors = NULL; + ctors_start = module_find_symbol("__ctors_start", module); + ctors_end = module_find_symbol("__ctors_end", module); -static int extract_operations(struct elf_module *module) { - Elf32_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module); - Elf32_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module); - Elf32_Sym *main_sym = module_find_symbol("main", module); - - if (init_sym) { - module->init_func = (module_init_t*)module_get_absolute( - init_sym->st_value, module); - if (*(module->init_func) == NULL) { - module->init_func = NULL; + if (ctors_start && ctors_end) { + module_ctor_t *start, *end; + int nr_ctors = 0; + int i, size; + + start = module_get_absolute(ctors_start->st_value, module); + end = module_get_absolute(ctors_end->st_value, module); + + nr_ctors = end - start; + + size = nr_ctors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + ctors = malloc(size); + if (!ctors) { + printf("Unable to alloc memory for ctors\n"); + return -1; } + + memset(ctors, 0, size); + for (i = 0; i < nr_ctors; i++) + ctors[i] = start[i]; + + module->ctors = ctors; } - if (exit_sym) { - module->exit_func = (module_exit_t*)module_get_absolute( - exit_sym->st_value, module); - if (*(module->exit_func) == NULL) { - module->exit_func = NULL; + dtors_start = module_find_symbol("__dtors_start", module); + dtors_end = module_find_symbol("__dtors_end", module); + + if (dtors_start && dtors_end) { + module_ctor_t *start, *end; + int nr_dtors = 0; + int i, size; + + start = module_get_absolute(dtors_start->st_value, module); + end = module_get_absolute(dtors_end->st_value, module); + + nr_dtors = end - start; + + size = nr_dtors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + dtors = malloc(size); + if (!dtors) { + printf("Unable to alloc memory for dtors\n"); + free(ctors); + return -1; } - } - if (main_sym) - module->main_func = - module_get_absolute(main_sym->st_value, module); + memset(dtors, 0, size); + for (i = 0; i < nr_dtors; i++) + dtors[i] = start[i]; + + module->dtors = dtors; + } return 0; } @@ -436,12 +475,14 @@ static int extract_operations(struct elf_module *module) { // Loads the module into the system int module_load(struct elf_module *module) { int res; + Elf32_Sym *main_sym; Elf32_Ehdr elf_hdr; + module_ctor_t *ctor; // Do not allow duplicate modules if (module_find(module->name) != NULL) { DBG_PRINT("Module %s is already loaded.\n", module->name); - return -1; + return EEXIST; } // Get a mapping/copy of the ELF file in memory @@ -467,42 +508,35 @@ int module_load(struct elf_module *module) { CHECKED(res, load_segments(module, &elf_hdr), error); //printf("bleah... 3\n"); // Obtain dynamic linking information - nr_needed = 0; CHECKED(res, prepare_dynlinking(module), error); //printf("check... 4\n"); - // - //dump_elf_module(module); /* Find modules we need to load as dependencies */ if (module->str_table) { - int i, n; + int i; /* - * nr_needed can be modified by recursive calls to - * module_load() so keep a local copy on the stack. + * Note that we have to load the dependencies in + * reverse order. */ - n = nr_needed; - for (i = 0; i < n; i++) { - size_t len, j; + for (i = module->nr_needed - 1; i >= 0; i--) { char *dep, *p; + char *argv[2] = { NULL, NULL }; - dep = module->str_table + needed[i]; + dep = module->str_table + module->needed[i]; /* strip everything but the last component */ - j = len = strlen(dep); - if (!len) + if (!strlen(dep)) continue; - p = dep + len - 1; - while (j > 0 && *p && *p != '/') { - p--; - j--; - } + if (strchr(dep, '/')) { + p = strrchr(dep, '/'); + p++; + } else + p = dep; - if (*p++ == '/') { - char argv[2] = { p, NULL }; - spawn_load(p, 1, argv); - } + argv[0] = p; + spawn_load(p, 1, argv); } } @@ -510,8 +544,11 @@ int module_load(struct elf_module *module) { CHECKED(res, check_symbols(module), error); //printf("check... 5\n"); - // Obtain constructors and destructors - CHECKED(res, extract_operations(module), error); + main_sym = module_find_symbol("main", module); + if (main_sym) + module->main_func = + module_get_absolute(main_sym->st_value, module); + //printf("check... 6\n"); // Add the module at the beginning of the module list @@ -520,6 +557,9 @@ int module_load(struct elf_module *module) { // Perform the relocations resolve_symbols(module); + // Obtain constructors and destructors + CHECKED(res, extract_operations(module), error); + //dprintf("module->symtable_size = %d\n", module->symtable_size); //print_elf_symbols(module); @@ -534,6 +574,10 @@ int module_load(struct elf_module *module) { (module->init_func == NULL) ? NULL : *(module->init_func), (module->exit_func == NULL) ? NULL : *(module->exit_func)); */ + + for (ctor = module->ctors; *ctor; ctor++) + (*ctor) (); + return 0; error: diff --git a/com32/lib/sys/module/i386/elfutils.h b/com32/lib/sys/module/i386/elfutils.h deleted file mode 100644 index b18968f3..00000000 --- a/com32/lib/sys/module/i386/elfutils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef ELF_UTILS_H_ -#define ELF_UTILS_H_ - -#include <elf.h> -#include <stdlib.h> - -/** - * elf_get_header - Returns a pointer to the ELF header structure. - * @elf_image: pointer to the ELF file image in memory - */ -static inline Elf32_Ehdr *elf_get_header(void *elf_image) { - return (Elf32_Ehdr*)elf_image; -} - -/** - * elf_get_pht - Returns a pointer to the first entry in the PHT. - * @elf_image: pointer to the ELF file image in memory - */ -static inline Elf32_Phdr *elf_get_pht(void *elf_image) { - Elf32_Ehdr *elf_hdr = elf_get_header(elf_image); - - return (Elf32_Phdr*)((Elf32_Off)elf_hdr + elf_hdr->e_phoff); -} - -// -/** - * elf_get_ph - Returns the element with the given index in the PTH - * @elf_image: pointer to the ELF file image in memory - * @index: the index of the PHT entry to look for - */ -static inline Elf32_Phdr *elf_get_ph(void *elf_image, int index) { - Elf32_Phdr *elf_pht = elf_get_pht(elf_image); - Elf32_Ehdr *elf_hdr = elf_get_header(elf_image); - - return (Elf32_Phdr*)((Elf32_Off)elf_pht + index * elf_hdr->e_phentsize); -} - -/** - * elf_hash - Returns the index in a SysV hash table for the symbol name. - * @name: the name of the symbol to look for - */ -extern unsigned long elf_hash(const unsigned char *name); - -/** - * elf_gnu_hash - Returns the index in a GNU hash table for the symbol name. - * @name: the name of the symbol to look for - */ -extern unsigned long elf_gnu_hash(const unsigned char *name); - -/** - * elf_malloc - Allocates memory to be used by ELF module contents. - * @memptr: pointer to a variable to hold the address of the allocated block. - * @alignment: alignment constraints of the block - * @size: the required size of the block - */ -extern int elf_malloc(void **memptr, size_t alignment, size_t size); - -/** - * elf_free - Releases memory previously allocated by elf_malloc. - * @memptr: the address of the allocated block - */ -extern void elf_free(void *memptr); - -#endif /*ELF_UTILS_H_*/ diff --git a/com32/lib/sys/module/shallow_module.c b/com32/lib/sys/module/shallow_module.c index fbcf781b..8a88e403 100644 --- a/com32/lib/sys/module/shallow_module.c +++ b/com32/lib/sys/module/shallow_module.c @@ -32,8 +32,8 @@ static int check_header_shallow(Elf32_Ehdr *elf_hdr) { static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr) { int i; int res = 0; - void *sht = NULL; - void *buffer = NULL; + char *sht = NULL; + char *buffer = NULL; Elf32_Shdr *crt_sht; Elf32_Off buff_offset; @@ -100,8 +100,8 @@ static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr) // Setup module information module->module_size = max_offset - min_offset; - module->str_table = (char*)(module->module_addr + (str_offset - min_offset)); - module->sym_table = module->module_addr + (sym_offset - min_offset); + module->str_table = (char *)module->module_addr + (str_offset - min_offset); + module->sym_table = (char *)module->module_addr + (sym_offset - min_offset); out: // Release the SHT diff --git a/com32/lib/sys/module/x86_64/common.c b/com32/lib/sys/module/x86_64/common.c deleted file mode 100644 index ba4dbedc..00000000 --- a/com32/lib/sys/module/x86_64/common.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * common.c - * - * Created on: Aug 11, 2008 - * Author: Stefan Bucur <stefanb@zytor.com> - */ - -#include <stdio.h> -#include <elf.h> -#include <string.h> -#include <fs.h> - -#include <linux/list.h> -#include <sys/module.h> - -#include "elfutils.h" -#include "common.h" - -/** - * The one and only list of loaded modules - */ -LIST_HEAD(modules_head); - -// User-space debugging routines -#ifdef ELF_DEBUG -void print_elf_ehdr(Elf64_Ehdr *ehdr) { - int i; - - fprintf(stderr, "Identification:\t"); - for (i=0; i < EI_NIDENT; i++) { - printf("%d ", ehdr->e_ident[i]); - } - fprintf(stderr, "\n"); - fprintf(stderr, "Type:\t\t%u\n", ehdr->e_type); - fprintf(stderr, "Machine:\t%u\n", ehdr->e_machine); - fprintf(stderr, "Version:\t%u\n", ehdr->e_version); - fprintf(stderr, "Entry:\t\t0x%08x\n", ehdr->e_entry); - fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff); - fprintf(stderr, "SHT Offset:\t0x%08x\n", ehdr->e_shoff); - //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags); - //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf64_Ehdr)); - fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum, - ehdr->e_shnum); -} - -void print_elf_symbols(struct elf_module *module) { - unsigned int i; - Elf64_Sym *crt_sym; - - for (i = 1; i < module->symtable_size; i++) - { - crt_sym = (Elf64_Sym*)(module->sym_table + i*module->syment_size); - - fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value); - - } -} -#endif //ELF_DEBUG - -static FILE *findpath(char *name) -{ - char path[FILENAME_MAX]; - FILE *f; - char *p, *n; - int i; - - p = PATH; -again: - memset(path, '\0', sizeof(path)); - i = 0; - while (*p && *p != ':' && i < FILENAME_MAX) { - path[i++] = *p++; - } - - if (*p == ':') - p++; - - if (!strcmp(path, ".")) { - if (!core_getcwd(path, sizeof(path))) { - DBG_PRINT("Could not get cwd\n"); - return NULL; - } - i = strlen(path); - } - - n = name; - while (*n && i < FILENAME_MAX) - path[i++] = *n++; - path[i] = '\0'; - - f = fopen(path, "rb"); - if (f) - return f; - - if (p >= PATH && p < PATH + strlen(PATH)) - goto again; - - return NULL; -} - -/* - * Image files manipulation routines - */ - -int image_load(struct elf_module *module) -{ - module->u.l._file = findpath(module->name); - - if (module->u.l._file == NULL) { - DBG_PRINT("Could not open object file '%s'\n", module->name); - goto error; - } - - module->u.l._cr_offset = 0; - - return 0; - -error: - if (module->u.l._file != NULL) { - fclose(module->u.l._file); - module->u.l._file = NULL; - } - - return -1; -} - - -int image_unload(struct elf_module *module) { - if (module->u.l._file != NULL) { - fclose(module->u.l._file); - module->u.l._file = NULL; - - } - module->u.l._cr_offset = 0; - - return 0; -} - -int image_read(void *buff, size_t size, struct elf_module *module) { - size_t result = fread(buff, size, 1, module->u.l._file); - - if (result < 1) - return -1; - - module->u.l._cr_offset += size; - return 0; -} - -int image_skip(size_t size, struct elf_module *module) { - void *skip_buff = NULL; - size_t result; - - if (size == 0) - return 0; - - skip_buff = malloc(size); - result = fread(skip_buff, size, 1, module->u.l._file); - free(skip_buff); - - if (result < 1) - return -1; - - module->u.l._cr_offset += size; - return 0; -} - -int image_seek(Elf64_Off offset, struct elf_module *module) { - if (offset < module->u.l._cr_offset) // Cannot seek backwards - return -1; - - return image_skip(offset - module->u.l._cr_offset, module); -} - - -// Initialization of the module subsystem -int modules_init(void) { - return 0; -} - -// Termination of the module subsystem -void modules_term(void) { - -} - -// Allocates the structure for a new module -struct elf_module *module_alloc(const char *name) { - struct elf_module *result = malloc(sizeof(struct elf_module)); - - memset(result, 0, sizeof(struct elf_module)); - - INIT_LIST_HEAD(&result->list); - INIT_LIST_HEAD(&result->required); - INIT_LIST_HEAD(&result->dependants); - - strncpy(result->name, name, MODULE_NAME_SIZE); - - return result; -} - -struct module_dep *module_dep_alloc(struct elf_module *module) { - struct module_dep *result = malloc(sizeof(struct module_dep)); - - INIT_LIST_HEAD (&result->list); - - result->module = module; - - return result; -} - -struct elf_module *module_find(const char *name) { - struct elf_module *cr_module; - - for_each_module(cr_module) { - if (strcmp(cr_module->name, name) == 0) - return cr_module; - } - - return NULL; -} - - -// Performs verifications on ELF header to assure that the open file is a -// valid SYSLINUX ELF module. -int check_header_common(Elf64_Ehdr *elf_hdr) { - // Check the header magic - if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 || - elf_hdr->e_ident[EI_MAG1] != ELFMAG1 || - elf_hdr->e_ident[EI_MAG2] != ELFMAG2 || - elf_hdr->e_ident[EI_MAG3] != ELFMAG3) { - - DBG_PRINT("The file is not an ELF object\n"); - return -1; - } - - if (elf_hdr->e_ident[EI_CLASS] != MODULE_ELF_CLASS) { - DBG_PRINT("Invalid ELF class code\n"); - return -1; - } - - if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) { - DBG_PRINT("Invalid ELF data encoding\n"); - return -1; - } - - if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION || - elf_hdr->e_version != MODULE_ELF_VERSION) { - DBG_PRINT("Invalid ELF file version\n"); - return -1; - } - - if (elf_hdr->e_machine != MODULE_ELF_MACHINE) { - DBG_PRINT("Invalid ELF architecture\n"); - return -1; - } - - return 0; -} - - -int enforce_dependency(struct elf_module *req, struct elf_module *dep) { - struct module_dep *crt_dep; - struct module_dep *new_dep; - - list_for_each_entry(crt_dep, &req->dependants, list) { - if (crt_dep->module == dep) { - // The dependency is already enforced - return 0; - } - } - - new_dep = module_dep_alloc(req); - list_add(&new_dep->list, &dep->required); - - new_dep = module_dep_alloc(dep); - list_add(&new_dep->list, &req->dependants); - - return 0; -} - -int clear_dependency(struct elf_module *req, struct elf_module *dep) { - struct module_dep *crt_dep = NULL; - int found = 0; - - list_for_each_entry(crt_dep, &req->dependants, list) { - if (crt_dep->module == dep) { - found = 1; - break; - } - } - - if (found) { - list_del(&crt_dep->list); - free(crt_dep); - } - - found = 0; - - list_for_each_entry(crt_dep, &dep->required, list) { - if (crt_dep->module == req) { - found = 1; - break; - } - } - - if (found) { - list_del(&crt_dep->list); - free(crt_dep); - } - - return 0; -} - -int check_symbols(struct elf_module *module) -{ - unsigned int i; - Elf64_Sym *crt_sym = NULL, *ref_sym = NULL; - char *crt_name; - struct elf_module *crt_module; - - int strong_count; - int weak_count; - - for(i = 1; i < module->symtable_size; i++) - { - crt_sym = (Elf64_Sym*)(module->sym_table + i * module->syment_size); - crt_name = module->str_table + crt_sym->st_name; - - strong_count = 0; - weak_count = 0; - - for_each_module(crt_module) - { - ref_sym = module_find_symbol(crt_name, crt_module); - - // If we found a definition for our symbol... - if (ref_sym != NULL && ref_sym->st_shndx != SHN_UNDEF) - { - switch (ELF64_ST_BIND(ref_sym->st_info)) - { - case STB_GLOBAL: - strong_count++; - break; - case STB_WEAK: - weak_count++; - break; - } - } - } - - if (crt_sym->st_shndx == SHN_UNDEF) - { - // We have an undefined symbol - if (strong_count == 0 && weak_count == 0) - { - DBG_PRINT("Symbol %s is undefined\n", crt_name); - //printf("Undef symbol FAIL: %s\n",crt_name); - return -1; - } - } - else - { - if (strong_count > 0 && ELF64_ST_BIND(ref_sym->st_info) == STB_GLOBAL) - { - // It's not an error - at relocation, the most recent symbol - // will be considered - DBG_PRINT("Info: Symbol %s is defined more than once\n", crt_name); - } - } - //printf("symbol %s laoded from %d\n",crt_name,crt_sym->st_value); - } - - return 0; -} - -int module_unloadable(struct elf_module *module) { - if (!list_empty(&module->dependants)) - return 0; - - return 1; -} - - -// Unloads the module from the system and releases all the associated memory -int module_unload(struct elf_module *module) { - struct module_dep *crt_dep, *tmp; - // Make sure nobody needs us - if (!module_unloadable(module)) { - DBG_PRINT("Module is required by other modules.\n"); - return -1; - } - - // Remove any dependency information - list_for_each_entry_safe(crt_dep, tmp, &module->required, list) { - clear_dependency(crt_dep->module, module); - } - - // Remove the module from the module list - list_del_init(&module->list); - - // Release the loaded segments or sections - if (module->module_addr != NULL) { - elf_free(module->module_addr); - - DBG_PRINT("%s MODULE %s UNLOADED\n", module->shallow ? "SHALLOW" : "", - module->name); - } - // Release the module structure - free(module); - - return 0; -} - - -static Elf64_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { - unsigned long h = elf_hash((const unsigned char*)name); - Elf64_Word *cr_word = module->hash_table; - - Elf64_Word nbucket = *cr_word++; - cr_word++; // Skip nchain - - Elf64_Word *bkt = cr_word; - Elf64_Word *chn = cr_word + nbucket; - - Elf64_Word crt_index = bkt[h % module->hash_table[0]]; - Elf64_Sym *crt_sym; - - - while (crt_index != STN_UNDEF) { - crt_sym = (Elf64_Sym*)(module->sym_table + crt_index*module->syment_size); - - if (strcmp(name, module->str_table + crt_sym->st_name) == 0) - return crt_sym; - - crt_index = chn[crt_index]; - } - - return NULL; -} - -static Elf64_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { - unsigned long h = elf_gnu_hash((const unsigned char*)name); - - // Setup code (TODO: Optimize this by computing only once) - Elf64_Word *cr_word = module->ghash_table; - Elf64_Word nbucket = *cr_word++; - Elf64_Word symbias = *cr_word++; - Elf64_Word bitmask_nwords = *cr_word++; - - if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) { - DBG_PRINT("Invalid GNU Hash structure\n"); - return NULL; - } - - Elf64_Word gnu_shift = *cr_word++; - - Elf64_Addr *gnu_bitmask = cr_word; - cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords; - - Elf64_Word *gnu_buckets = cr_word; - cr_word += nbucket; - - Elf64_Word *gnu_chain_zero = cr_word - symbias; - - // Computations - /* bitask words are 64bit for ELFCLASS64 modules */ - Elf64_Xword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & - (bitmask_nwords - 1)]; - - unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1); - unsigned int hashbit2 = (h >> gnu_shift) & (MODULE_ELF_CLASS_SIZE - 1); - - if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) { - unsigned long rem; - Elf64_Word bucket; - - rem = h % nbucket; - - bucket = gnu_buckets[rem]; - - if (bucket != 0) { - const Elf64_Word* hasharr = &gnu_chain_zero[bucket]; - - do { - if (((*hasharr ^ h ) >> 1) == 0) { - Elf64_Sym *crt_sym = (Elf64_Sym*)(module->sym_table + - (hasharr - gnu_chain_zero) * module->syment_size); - - if (strcmp(name, module->str_table + crt_sym->st_name) == 0) { - return crt_sym; - } - } - } while ((*hasharr++ & 1u) == 0); - } - } - - return NULL; -} - -static Elf64_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) -{ - - unsigned int i; - Elf64_Sym *crt_sym; - - for (i=1; i < module->symtable_size; i++) - { - crt_sym = (Elf64_Sym*)(module->sym_table + i*module->syment_size); - if (strcmp(name, module->str_table + crt_sym->st_name) == 0) - { - return crt_sym; - } - } - - return NULL; -} - -Elf64_Sym *module_find_symbol(const char *name, struct elf_module *module) { - Elf64_Sym *result = NULL; - - if (module->ghash_table != NULL) - result = module_find_symbol_gnu(name, module); - - if (result == NULL) - { - if (module->hash_table != NULL) - { - result = module_find_symbol_sysv(name, module); - } - else - { - result = module_find_symbol_iterate(name, module); - } - } - - return result; -} - -Elf64_Sym *global_find_symbol(const char *name, struct elf_module **module) { - struct elf_module *crt_module; - Elf64_Sym *crt_sym = NULL; - Elf64_Sym *result = NULL; - - for_each_module(crt_module) { - crt_sym = module_find_symbol(name, crt_module); - - if (crt_sym != NULL && crt_sym->st_shndx != SHN_UNDEF) { - switch (ELF64_ST_BIND(crt_sym->st_info)) { - case STB_GLOBAL: - if (module != NULL) { - *module = crt_module; - } - return crt_sym; - case STB_WEAK: - // Consider only the first weak symbol - if (result == NULL) { - if (module != NULL) { - *module = crt_module; - } - result = crt_sym; - } - break; - } - } - } - - return result; -} diff --git a/com32/lib/sys/module/x86_64/elf_module.c b/com32/lib/sys/module/x86_64/elf_module.c index 2ff2e20b..3c164996 100644 --- a/com32/lib/sys/module/x86_64/elf_module.c +++ b/com32/lib/sys/module/x86_64/elf_module.c @@ -5,20 +5,20 @@ * Author: Stefan Bucur <stefanb@zytor.com> */ - +#include <errno.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <elf.h> #include <dprintf.h> +#include <core.h> #include <linux/list.h> #include <sys/module.h> +#include <sys/exec.h> #include "elfutils.h" -#include "common.h" - -#define MAX_NR_DEPS 64 +#include "../common.h" static int check_header(Elf64_Ehdr *elf_hdr) { int res; @@ -50,7 +50,7 @@ static int check_header(Elf64_Ehdr *elf_hdr) { static int load_segments(struct elf_module *module, Elf64_Ehdr *elf_hdr) { int i; int res = 0; - void *pht = NULL; + char *pht = NULL; Elf64_Phdr *cr_pht; Elf64_Addr min_addr = 0x0000000000000000; // Min. ELF vaddr @@ -136,8 +136,8 @@ static int load_segments(struct elf_module *module, Elf64_Ehdr *elf_hdr) { // headers Elf64_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; - if (image_read(module_get_absolute(cr_pht->p_vaddr, module) + aux_off, - cr_pht->p_filesz - aux_off, module) < 0) { + if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, + cr_pht->p_filesz - aux_off, module) < 0) { res = -1; goto out; } @@ -180,9 +180,6 @@ out: return res; } -static int nr_needed; -static Elf64_Word needed[MAX_NR_DEPS];; - static int prepare_dynlinking(struct elf_module *module) { Elf64_Dyn *dyn_entry = module->dyn_table; @@ -195,8 +192,8 @@ static int prepare_dynlinking(struct elf_module *module) { * are then inform the user that we ran out of * space. */ - if (nr_needed < MAX_NR_DEPS) - needed[nr_needed++] = dyn_entry->d_un.d_ptr; + if (module->nr_needed < MAX_NR_DEPS) + module->needed[module->nr_needed++] = dyn_entry->d_un.d_ptr; else { printf("Too many dependencies!\n"); return -1; @@ -242,6 +239,11 @@ static int prepare_dynlinking(struct elf_module *module) { return 0; } +void undefined_symbol(void) +{ + printf("Error: An undefined symbol was referenced\n"); + kaboom(); +} static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) { Elf64_Xword *dest = module_get_absolute(rel->r_offset, module); @@ -259,8 +261,7 @@ static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) { // Find out details about the symbol // The symbol reference - Elf64_Sym *sym_ref = - (Elf64_Sym*)(module->sym_table + sym * module->syment_size); + Elf64_Sym *sym_ref = symbol_get_entry(module, sym); // The symbol definition sym_def = @@ -268,11 +269,16 @@ static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) { &sym_module); if (sym_def == NULL) { - // This should never happen DBG_PRINT("Cannot perform relocation for symbol %s\n", module->str_table + sym_ref->st_name); - return -1; + if (ELF64_ST_BIND(sym_ref->st_info) != STB_WEAK) + return -1; + + // This must be a derivative-specific + // function. We're OK as long as we never + // execute the function. + sym_def = global_find_symbol("undefined_symbol", &sym_module); } // Compute the absolute symbol virtual address @@ -422,73 +428,93 @@ static int resolve_symbols(struct elf_module *module) { res = perform_relocation(module, crt_rel); - if (res < 0) { + if (res < 0) return res; - } } } return 0; } +static int extract_operations(struct elf_module *module) { + Elf64_Sym *ctors_start, *ctors_end; + Elf64_Sym *dtors_start, *dtors_end; + module_ctor_t *ctors = NULL; + module_ctor_t *dtors = NULL; + ctors_start = module_find_symbol("__ctors_start", module); + ctors_end = module_find_symbol("__ctors_end", module); -static int extract_operations(struct elf_module *module) { - Elf64_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module); - Elf64_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module); - Elf64_Sym *main_sym = module_find_symbol("main", module); - - if (init_sym) { - module->init_func = (module_init_t*)module_get_absolute( - init_sym->st_value, module); - if (*(module->init_func) == NULL) { - module->init_func = NULL; - } - } + if (ctors_start && ctors_end) { + module_ctor_t *start, *end; + int nr_ctors = 0; + int i, size; + + start = module_get_absolute(ctors_start->st_value, module); + end = module_get_absolute(ctors_end->st_value, module); + + nr_ctors = end - start; - if (exit_sym) { - module->exit_func = (module_exit_t*)module_get_absolute( - exit_sym->st_value, module); - if (*(module->exit_func) == NULL) { - module->exit_func = NULL; + size = nr_ctors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + ctors = malloc(size); + if (!ctors) { + printf("Unable to alloc memory for ctors\n"); + return -1; } + + memset(ctors, 0, size); + for (i = 0; i < nr_ctors; i++) + ctors[i] = start[i]; + + module->ctors = ctors; } - if (main_sym) - module->main_func = - module_get_absolute(main_sym->st_value, module); + dtors_start = module_find_symbol("__dtors_start", module); + dtors_end = module_find_symbol("__dtors_end", module); - return 0; -} + if (dtors_start && dtors_end) { + module_ctor_t *start, *end; + int nr_dtors = 0; + int i, size; -void print_elf_ehdr(Elf64_Ehdr *ehdr) { - int i; + start = module_get_absolute(dtors_start->st_value, module); + end = module_get_absolute(dtors_end->st_value, module); + + nr_dtors = end - start; + + size = nr_dtors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + dtors = malloc(size); + if (!dtors) { + printf("Unable to alloc memory for dtors\n"); + free(ctors); + return -1; + } - printf("Identification:\t"); - for (i=0; i < EI_NIDENT; i++) { - printf("%d ", ehdr->e_ident[i]); + memset(dtors, 0, size); + for (i = 0; i < nr_dtors; i++) + dtors[i] = start[i]; + + module->dtors = dtors; } - printf("\n"); - printf("Type:\t\t%u\n", ehdr->e_type); - printf("Machine:\t%u\n", ehdr->e_machine); - printf("Version:\t%u\n", ehdr->e_version); - printf("Entry:\t\t0x%08x\n", ehdr->e_entry); - printf("PHT Offset:\t0x%08x\n", ehdr->e_phoff); - printf("SHT Offset:\t0x%08x\n", ehdr->e_shoff); - //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags); - //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf64_Ehdr)); - printf("phnum: %d shnum: %d\n", ehdr->e_phnum, - ehdr->e_shnum); + + return 0; } + // Loads the module into the system int module_load(struct elf_module *module) { int res; + Elf64_Sym *main_sym; Elf64_Ehdr elf_hdr; + module_ctor_t *ctor; // Do not allow duplicate modules if (module_find(module->name) != NULL) { DBG_PRINT("Module %s is already loaded.\n", module->name); - return -1; + return EEXIST; } // Get a mapping/copy of the ELF file in memory @@ -512,45 +538,37 @@ int module_load(struct elf_module *module) { // Load the segments in the memory CHECKED(res, load_segments(module, &elf_hdr), error); - //!!!!! Passed load_segments.... //printf("bleah... 3\n"); // Obtain dynamic linking information - nr_needed = 0; CHECKED(res, prepare_dynlinking(module), error); //printf("check... 4\n"); - // - //dump_elf_module(module); /* Find modules we need to load as dependencies */ if (module->str_table) { - int i, n; + int i; /* - * nr_needed can be modified by recursive calls to - * module_load() so keep a local copy on the stack. + * Note that we have to load the dependencies in + * reverse order. */ - n = nr_needed; - for (i = 0; i < n; i++) { - size_t len, j; + for (i = module->nr_needed - 1; i >= 0; i--) { char *dep, *p; + char *argv[2] = { NULL, NULL }; - dep = module->str_table + needed[i]; + dep = module->str_table + module->needed[i]; /* strip everything but the last component */ - j = len = strlen(dep); - if (!len) + if (!strlen(dep)) continue; - p = dep + len - 1; - while (j > 0 && *p && *p != '/') { - p--; - j--; - } + if (strchr(dep, '/')) { + p = strrchr(dep, '/'); + p++; + } else + p = dep; - if (*p++ == '/') { - char argv[2] = { p, NULL }; - spawn_load(p, 1, argv); - } + argv[0] = p; + spawn_load(p, 1, argv); } } @@ -558,8 +576,11 @@ int module_load(struct elf_module *module) { CHECKED(res, check_symbols(module), error); //printf("check... 5\n"); - // Obtain constructors and destructors - CHECKED(res, extract_operations(module), error); + main_sym = module_find_symbol("main", module); + if (main_sym) + module->main_func = + module_get_absolute(main_sym->st_value, module); + //printf("check... 6\n"); // Add the module at the beginning of the module list @@ -568,6 +589,9 @@ int module_load(struct elf_module *module) { // Perform the relocations resolve_symbols(module); + // Obtain constructors and destructors + CHECKED(res, extract_operations(module), error); + //dprintf("module->symtable_size = %d\n", module->symtable_size); //print_elf_symbols(module); @@ -582,6 +606,10 @@ int module_load(struct elf_module *module) { (module->init_func == NULL) ? NULL : *(module->init_func), (module->exit_func == NULL) ? NULL : *(module->exit_func)); */ + + for (ctor = module->ctors; *ctor; ctor++) + (*ctor) (); + return 0; error: diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c index a0ef1597..3221bb60 100644 --- a/com32/lib/sys/open.c +++ b/com32/lib/sys/open.c @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <fcntl.h> +#include <fs.h> #include "file.h" /* diff --git a/com32/lib/sys/rawcon_read.c b/com32/lib/sys/rawcon_read.c index e6635909..7eae95f1 100644 --- a/com32/lib/sys/rawcon_read.c +++ b/com32/lib/sys/rawcon_read.c @@ -35,51 +35,38 @@ #include <errno.h> #include <string.h> #include <com32.h> +#include <core.h> #include <minmax.h> #include "file.h" /* Global, since it's used by stdcon_read */ -#ifndef SYSLINUX_EFI ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count) { - com32sys_t ireg, oreg; char *bufp = buf; size_t n = 0; + char hi = 0; -printf("__rawcon_read... enter\n"); (void)fp; - memset(&ireg, 0, sizeof ireg); - while (n < count) { + if (hi) { + *bufp++ = hi; + n++; + hi = 0; + continue; + } + /* Poll */ - ireg.eax.b[1] = 0x0B; - __intcall(0x21, &ireg, &oreg); - if (!oreg.eax.b[0]) + if (!pollchar()) break; /* We have data, go get it */ - ireg.eax.b[1] = 0x08; - __intcall(0x21, &ireg, &oreg); - *bufp++ = oreg.eax.b[0]; + *bufp++ = getchar(&hi); n++; } return n; } -#else -ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count) -{ - extern char getchar(); - char *bufp = buf; - size_t n = 0; - while (n < count) { - *bufp++ = getchar(); - n++; - } - return n; -} -#endif const struct input_dev dev_rawcon_r = { .dev_magic = __DEV_MAGIC, diff --git a/com32/lib/sys/rawcon_write.c b/com32/lib/sys/rawcon_write.c index 2d45a7b2..1f7920b2 100644 --- a/com32/lib/sys/rawcon_write.c +++ b/com32/lib/sys/rawcon_write.c @@ -34,24 +34,20 @@ #include <errno.h> #include <string.h> #include <com32.h> +#include <core.h> #include <minmax.h> #include "file.h" static ssize_t __rawcon_write(struct file_info *fp, const void *buf, size_t count) { - com32sys_t ireg; const char *bufp = buf; size_t n = 0; (void)fp; - memset(&ireg, 0, sizeof ireg); - ireg.eax.b[1] = 0x02; - while (count--) { - ireg.edx.b[0] = *bufp++; - __intcall(0x21, &ireg, NULL); + writechr(*bufp++); n++; } diff --git a/com32/lib/sys/serial_write.c b/com32/lib/sys/serial_write.c index fa0f4f4d..3f949fb7 100644 --- a/com32/lib/sys/serial_write.c +++ b/com32/lib/sys/serial_write.c @@ -34,13 +34,13 @@ #include <errno.h> #include <string.h> #include <com32.h> +#include <core.h> #include <minmax.h> #include <syslinux/config.h> #include "file.h" ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count) { - com32sys_t ireg; const char *bufp = buf; size_t n = 0; @@ -49,12 +49,8 @@ ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count) if (!syslinux_serial_console_info()->iobase) return count; /* Nothing to do */ - memset(&ireg, 0, sizeof ireg); - ireg.eax.b[1] = 0x04; - while (count--) { - ireg.edx.b[0] = *bufp++; - __intcall(0x21, &ireg, NULL); + write_serial(*bufp++); n++; } diff --git a/com32/lib/sys/stdcon_write.c b/com32/lib/sys/stdcon_write.c index 9cb2f7db..9bd225f9 100644 --- a/com32/lib/sys/stdcon_write.c +++ b/com32/lib/sys/stdcon_write.c @@ -34,6 +34,7 @@ #include <errno.h> #include <string.h> #include <com32.h> +#include <core.h> #include <minmax.h> #include "file.h" @@ -57,22 +58,16 @@ static int __stdcon_open(struct file_info *fp) static ssize_t __stdcon_write(struct file_info *fp, const void *buf, size_t count) { - com32sys_t ireg; const char *bufp = buf; size_t n = 0; (void)fp; - memset(&ireg, 0, sizeof ireg); - ireg.eax.b[1] = 0x02; - while (count--) { - if (*bufp == '\n') { - ireg.edx.b[0] = '\r'; - __intcall(0x21, &ireg, NULL); - } - ireg.edx.b[0] = *bufp++; - __intcall(0x21, &ireg, NULL); + if (*bufp == '\n') + writechr('\r'); + + writechr(*bufp++); n++; } diff --git a/com32/lib/sys/xserial_write.c b/com32/lib/sys/xserial_write.c index e399f5fc..8a4fb9e0 100644 --- a/com32/lib/sys/xserial_write.c +++ b/com32/lib/sys/xserial_write.c @@ -35,6 +35,7 @@ #include <errno.h> #include <string.h> #include <com32.h> +#include <core.h> #include <minmax.h> #include <colortbl.h> #include <syslinux/config.h> @@ -42,12 +43,7 @@ static void emit(char ch) { - static com32sys_t ireg; /* Zeroed with the BSS */ - - ireg.eax.b[1] = 0x04; - ireg.edx.b[0] = ch; - - __intcall(0x21, &ireg, NULL); + write_serial(ch); } ssize_t __xserial_write(struct file_info *fp, const void *buf, size_t count) |