diff options
Diffstat (limited to 'com32')
33 files changed, 1618 insertions, 406 deletions
diff --git a/com32/gfxboot/gfxboot.c b/com32/gfxboot/gfxboot.c index 35d180a6..aa05caf8 100644 --- a/com32/gfxboot/gfxboot.c +++ b/com32/gfxboot/gfxboot.c @@ -962,7 +962,7 @@ void boot_entry(menu_t *menu_ptr, char *arg) gfx_done(); - syslinux_boot_linux(kernel, kernel_size, initrd, arg); + syslinux_boot_linux(kernel, kernel_size, initrd, NULL, arg); } diff --git a/com32/gplinclude/dmi/dmi_bios.h b/com32/gplinclude/dmi/dmi_bios.h index 5d47e899..4af7e0bd 100644 --- a/com32/gplinclude/dmi/dmi_bios.h +++ b/com32/gplinclude/dmi/dmi_bios.h @@ -22,7 +22,7 @@ #define BIOS_BIOS_REVISION_SIZE 16 #define BIOS_FIRMWARE_REVISION_SIZE 16 -#define BIOS_CHAR_NB_ELEMENTS 28 +#define BIOS_CHAR_NB_ELEMENTS 29 #define BIOS_CHAR_X1_NB_ELEMENTS 8 #define BIOS_CHAR_X2_NB_ELEMENTS 3 @@ -46,6 +46,7 @@ typedef struct { bool boot_from_cd; bool selectable_boot; bool bios_rom_socketed; + bool boot_from_pcmcia; bool edd; bool japanese_floppy_nec_9800_1_2MB; bool japanese_floppy_toshiba_1_2MB; diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile index ea9ddfeb..add640a7 100644 --- a/com32/hdt/Makefile +++ b/com32/hdt/Makefile @@ -74,6 +74,8 @@ hdt.img: hdt.c32 $(FLOPPY_DIR)/hdt.cfg $(FLOPPY_DIR)/mtools.conf $(topdir)/mtool MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(FLOPPY_DIR)/syslinux.cfg a: MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(FLOPPY_DIR)/$(MEMTEST) a: MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(ART_DIR)/backgnd.png a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(ART_DIR)/display.png a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(ART_DIR)/red.png a: mv hdt.img hdt-$(VERSION).img ln -sf hdt-$(VERSION).img hdt.img @@ -94,6 +96,8 @@ hdt.iso: hdt.c32 $(topdir)/core/isolinux.bin $(FLOPPY_DIR)/hdt.cfg memtest cp $(MENU_COM32) $(ISO_DIR)/$(ISOLINUX_DIR) cp $(CHAIN_COM32) $(ISO_DIR)/$(ISOLINUX_DIR) cp -av $(ART_DIR)/backgnd.png $(ISO_DIR)/$(ISOLINUX_DIR) + cp -av $(ART_DIR)/display.png $(ISO_DIR)/$(ISOLINUX_DIR) + cp -av $(ART_DIR)/red.png $(ISO_DIR)/$(ISOLINUX_DIR) -[ ! -f $(GZ_PCI_IDS_FILE) ] && cp /usr/share/hwdata/pci.ids $(PCI_IDS_FILE) && $(GZIPPROG) $(PCI_IDS_FILE) -[ ! -f $(GZ_PCI_IDS_FILE) ] && cp /usr/share/pci.ids $(PCI_IDS_FILE) && $(GZIPPROG) $(PCI_IDS_FILE) -[ -f $(MODULES_ALIAS_FILE) ] && cp $(MODULES_ALIAS_FILE) $(ISO_DIR)/$(ISOLINUX_DIR)\ diff --git a/com32/hdt/art/display.png b/com32/hdt/art/display.png Binary files differnew file mode 100644 index 00000000..31fabef6 --- /dev/null +++ b/com32/hdt/art/display.png diff --git a/com32/hdt/art/red.png b/com32/hdt/art/red.png Binary files differnew file mode 100644 index 00000000..c5616ac2 --- /dev/null +++ b/com32/hdt/art/red.png diff --git a/com32/hdt/floppy/hdt.cfg b/com32/hdt/floppy/hdt.cfg index e5f3b0a0..524c4e06 100644 --- a/com32/hdt/floppy/hdt.cfg +++ b/com32/hdt/floppy/hdt.cfg @@ -93,7 +93,17 @@ TEXT HELP VESA mode is enabled ENDTEXT COM32 hdt.c32 -APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids quiet vesa nomenu auto='show memory;say `########`;say `Starting memtest in 5 sec`%5;exit' postexec='memtest' +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids quiet vesa nomenu auto='show memory;say `########`;say `Starting memtest in 5 sec`;sleep 5;exit' postexec='memtest' + +LABEL display +MENU LABEL Display feature (VESA mode) +TEXT HELP + Starts HDT using the Command Line Interface (CLI) + VESA mode is enabled + A Picture is shown by using the display command +ENDTEXT +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids silent nomenu vesa auto='display display.png; sleep 5000; display red.png' MENU SEPARATOR diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index f7f7e949..3c571d60 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -54,12 +54,12 @@ static void main_show_modes(int argc __unused, char **argv __unused, int i = 0; reset_more_printf(); - printf("Available modes:\n"); + more_printf("Available modes:\n"); while (list_modes[i]) { printf("%s ", list_modes[i]->name); i++; } - printf("\n"); + more_printf("\n"); } /** @@ -119,7 +119,7 @@ static void show_cli_help(int argc __unused, char **argv __unused, find_cli_mode_descr(hdt_cli.mode, ¤t_mode); - printf("Available commands are:\n"); + more_printf("Available commands are:\n"); /* List first default modules of the mode */ if (current_mode->default_modules && current_mode->default_modules->modules) { @@ -154,7 +154,7 @@ static void show_cli_help(int argc __unused, char **argv __unused, /* List secondly the show modules of the mode */ if (current_mode->show_modules && current_mode->show_modules->modules) { - printf("\nshow commands:\n"); + more_printf("\nshow commands:\n"); j = 0; while (current_mode->show_modules->modules[j].name) { printf("%s ", current_mode->show_modules->modules[j].name); @@ -165,7 +165,7 @@ static void show_cli_help(int argc __unused, char **argv __unused, /* List thirdly the set modules of the mode */ if (current_mode->set_modules && current_mode->set_modules->modules) { - printf("\nset commands:\n"); + more_printf("\nset commands:\n"); j = 0; while (current_mode->set_modules->modules[j].name) { printf("%s ", current_mode->set_modules->modules[j].name); @@ -260,6 +260,30 @@ static void do_dump(int argc __unused, char **argv __unused, } /** + * do_sleep - sleep a number of milliseconds + **/ +static void do_sleep(int argc , char **argv , + struct s_hardware *hardware) +{ + (void) hardware; + if (argc != 1) return; + more_printf("Sleep %d milliseconds\n",atoi(argv[0])); + msleep(atoi(argv[0])); +} + +/** + * do_display - display an image to user + **/ +static void do_display(int argc , char **argv , + struct s_hardware *hardware) +{ + (void) hardware; + if ((argc != 1) || (vesamode == false)) return; + more_printf("Display %s file\n",argv[0]); + vesacon_load_background(argv[0]); +} + +/** * do_say - say message to user **/ static void do_say(int argc , char **argv , @@ -270,7 +294,6 @@ static void do_say(int argc , char **argv , char text_to_say[255]={0}; int arg=0; - int sleep_time=0; #if DEBUG for (int i=0; i<argc;i++) dprintf("SAY: arg[%d]={%s}\n",i,argv[i]); #endif @@ -293,24 +316,7 @@ static void do_say(int argc , char **argv , dprintf("SAY CMD = [%s]\n",text_to_say); } - /* The % char can be in the same argument, let's consider it again */ - arg--; - - /* Searching for a % argument to determine the time to show the message */ - char *time_to_display = NULL; - /* Search for a requested time to display */ - while ( ((time_to_display=strchr(argument, '%')) == NULL) && (arg+1<argc)) { - arg++; - argument = (char *)argv[arg]; - } - - if (time_to_display != NULL) { - sleep_time=atoi(time_to_display+1); - dprintf("SAY CMD :Time to display = %d\n",sleep_time); - } - - printf("%s\n",text_to_say); - sleep(sleep_time); + more_printf("%s\n",text_to_say); } } @@ -357,6 +363,16 @@ struct cli_callback_descr list_hdt_default_modules[] = { .nomodule = true, }, { + .name = CLI_DISPLAY, + .exec = do_display, + .nomodule = true, + }, + { + .name = CLI_SLEEP, + .exec = do_sleep, + .nomodule = true, + }, + { .name = NULL, .exec = NULL, .nomodule = false}, diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 11984e5a..7542da83 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -132,7 +132,7 @@ void set_mode(cli_mode_t mode, struct s_hardware *hardware) break; case PXE_MODE: if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { - printf("You are not currently using PXELINUX\n"); + more_printf("You are not currently using PXELINUX\n"); break; } hdt_cli.mode = mode; @@ -160,7 +160,7 @@ void set_mode(cli_mode_t mode, struct s_hardware *hardware) break; case DMI_MODE: if (!hardware->is_dmi_valid) { - printf("No valid DMI table found, exiting.\n"); + more_printf("No valid DMI table found, exiting.\n"); break; } hdt_cli.mode = mode; @@ -172,7 +172,7 @@ void set_mode(cli_mode_t mode, struct s_hardware *hardware) break; case VPD_MODE: if (!hardware->is_vpd_valid) { - printf("No valid VPD table found, exiting.\n"); + more_printf("No valid VPD table found, exiting.\n"); break; } hdt_cli.mode = mode; @@ -188,9 +188,9 @@ void set_mode(cli_mode_t mode, struct s_hardware *hardware) break; default: /* Invalid mode */ - printf("Unknown mode, please choose among:\n"); + more_printf("Unknown mode, please choose among:\n"); while (list_modes[i]) { - printf("\t%s\n", list_modes[i]->name); + more_printf("\t%s\n", list_modes[i]->name); i++; } } @@ -199,7 +199,7 @@ void set_mode(cli_mode_t mode, struct s_hardware *hardware) /* There is not cli_mode_descr struct for the exit mode */ if (current_mode == NULL && hdt_cli.mode != EXIT_MODE) { /* Shouldn't get here... */ - printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); + more_printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); } } @@ -679,7 +679,7 @@ static void exec_command(char *line, struct s_hardware *hardware) if (current_module != NULL) current_module->exec(argc, argv, hardware); else - printf("unknown command: '%s'\n", command); + more_printf("unknown command: '%s'\n", command); } } else { /* @@ -833,7 +833,7 @@ void start_cli_mode(struct s_hardware *hardware) find_cli_mode_descr(hdt_cli.mode, ¤t_mode); if (current_mode == NULL) { /* Shouldn't get here... */ - printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); + more_printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); return; } @@ -842,7 +842,7 @@ void start_cli_mode(struct s_hardware *hardware) start_auto_mode(hardware); } - printf("Entering CLI mode\n"); + more_printf("Entering CLI mode\n"); reset_prompt(); diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 30fe5187..82a4fc99 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -67,6 +67,8 @@ #define CLI_DISABLE "disable" #define CLI_DUMP "dump" #define CLI_SAY "say" +#define CLI_DISPLAY "display" +#define CLI_SLEEP "sleep" typedef enum { INVALID_MODE, diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 8e9a9e64..dcad28cd 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -63,6 +63,9 @@ void detect_parameters(const int argc, const char *argv[], /* Quiet mode - make the output more quiet */ quiet = true; + /* Silent mode - make not output at all */ + silent = false; + /* Vesa mode isn't set until we explictly call it */ vesamode = false; @@ -75,6 +78,8 @@ void detect_parameters(const int argc, const char *argv[], for (int i = 1; i < argc; i++) { if (!strncmp(argv[i], "quiet", 5)) { quiet = true; + } else if (!strncmp(argv[i], "silent", 6)) { + silent = true; } else if (!strncmp(argv[i], "verbose", 7)) { quiet = false; } else if (!strncmp(argv[i], "modules_pcimap=", 15)) { @@ -739,8 +744,8 @@ void detect_hardware(struct s_hardware *hardware) if (!quiet) more_printf("DMI: Detecting Table\n"); if (detect_dmi(hardware) == -ENODMITABLE) { - printf("DMI: ERROR ! Table not found ! \n"); - printf("DMI: Many hardware components will not be detected ! \n"); + more_printf("DMI: ERROR ! Table not found ! \n"); + more_printf("DMI: Many hardware components will not be detected ! \n"); } else { if (!quiet) more_printf("DMI: Table found ! (version %u.%u)\n", diff --git a/com32/hdt/hdt-common.h b/com32/hdt/hdt-common.h index 8c85260b..c2299b48 100644 --- a/com32/hdt/hdt-common.h +++ b/com32/hdt/hdt-common.h @@ -87,6 +87,9 @@ struct upload_backend *upload; /* Defines if the cli is quiet*/ bool quiet; +/* Defines if the cli is totally silent*/ +bool silent; + /* Defines if we must use the vesa mode */ bool vesamode; @@ -114,16 +117,18 @@ extern bool disable_more_printf; * one \n (and only one) */ #define more_printf(...) do {\ - if (__likely(!disable_more_printf)) {\ - if (display_line_nb == max_console_lines) {\ - display_line_nb=0;\ - printf("\n--More--");\ - get_key(stdin, 0);\ - printf("\033[2K\033[1G\033[1F");\ + if (__likely(!silent)) {\ + if (__likely(!disable_more_printf)) {\ + if (display_line_nb == max_console_lines) {\ + display_line_nb=0;\ + printf("\n--More--");\ + get_key(stdin, 0);\ + printf("\033[2K\033[1G\033[1F");\ + }\ + display_line_nb++;\ }\ - display_line_nb++;\ + printf(__VA_ARGS__);\ }\ - printf(__VA_ARGS__);\ } while (0); /* Display CPU registers for debugging purposes */ diff --git a/com32/hdt/hdt-dump.c b/com32/hdt/hdt-dump.c index b963e19b..b1748c8e 100644 --- a/com32/hdt/hdt-dump.c +++ b/com32/hdt/hdt-dump.c @@ -156,7 +156,7 @@ void flush(ZZJSON_CONFIG * config, ZZJSON ** item) void dump(struct s_hardware *hardware) { if (hardware->is_pxe_valid == false) { - printf("PXE stack was not detected, Dump feature is not available\n"); + more_printf("PXE stack was not detected, Dump feature is not available\n"); return; } diff --git a/com32/hdt/hdt.c b/com32/hdt/hdt.c index 851b0462..653995d0 100644 --- a/com32/hdt/hdt.c +++ b/com32/hdt/hdt.c @@ -72,7 +72,7 @@ int main(const int argc, const char *argv[]) clear_screen(); printf("\033[1;1H"); - printf("%s\n", version_string); + more_printf("%s\n", version_string); int return_code = 0; @@ -86,7 +86,7 @@ int main(const int argc, const char *argv[]) /* Do we got request to do something at exit time ? */ if (strlen(hardware.postexec)>0) { - printf("Executing postexec instructions : %s\n",hardware.postexec); + more_printf("Executing postexec instructions : %s\n",hardware.postexec); runsyslinuxcmd(hardware.postexec); } diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h index 041d726d..e385417a 100644 --- a/com32/hdt/hdt.h +++ b/com32/hdt/hdt.h @@ -33,7 +33,7 @@ #define AUTHOR "Erwan Velu" #define CORE_DEVELOPER "Pierre-Alexandre Meyer" #define CONTACT "hdt@zytor.com" -#define VERSION "0.5.2-pre2" +#define VERSION "0.5.2" #define CODENAME "Manon" #define NB_CONTRIBUTORS 3 #define CONTRIBUTORS {"Sebastien Gonzalve (Patches)", "Gert Hulselmans (Tests)", "Alexander Andino (Design)"} diff --git a/com32/include/syslinux/linux.h b/com32/include/syslinux/linux.h index 754d1b64..f5f95fb0 100644 --- a/com32/include/syslinux/linux.h +++ b/com32/include/syslinux/linux.h @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2012 Intel Corporation; author: H. Peter Anvin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -51,8 +52,26 @@ struct initramfs { }; #define INITRAMFS_MAX_ALIGN 4096 +struct setup_data_header { + uint64_t next; + uint32_t type; + uint32_t len; +} __packed; + +struct setup_data { + struct setup_data *prev, *next; + const void *data; + struct setup_data_header hdr; +}; + +#define SETUP_NONE 0 +#define SETUP_E820_EXT 1 +#define SETUP_DTB 2 + int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, - struct initramfs *initramfs, char *cmdline); + struct initramfs *initramfs, + struct setup_data *setup_data, + char *cmdline); /* Initramfs manipulation functions */ @@ -70,4 +89,12 @@ int initramfs_load_file(struct initramfs *ihead, const char *src_filename, int initramfs_add_trailer(struct initramfs *ihead); int initramfs_load_archive(struct initramfs *ihead, const char *filename); +/* Setup data manipulation functions */ + +struct setup_data *setup_data_init(void); +int setup_data_add(struct setup_data *head, uint32_t type, + const void *data, size_t data_len); +int setup_data_load(struct setup_data *head, uint32_t type, + const char *filename); + #endif /* _SYSLINUX_LINUX_H */ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index eace321b..5ab1fac4 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -129,7 +129,9 @@ LIBOBJS = \ syslinux/video/fontquery.o syslinux/video/forcetext.o \ syslinux/video/reportmode.o \ \ - syslinux/disk.o + syslinux/disk.o \ + \ + syslinux/setup_data.o # These are the objects which are also imported into the core LIBCOREOBJS = \ diff --git a/com32/lib/com32.ld b/com32/lib/com32.ld index 37ee46cf..008e4ceb 100644 --- a/com32/lib/com32.ld +++ b/com32/lib/com32.ld @@ -36,36 +36,23 @@ SECTIONS .rodata1 : { *(.rodata1) } __rodata_end = .; - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ + /* + * The difference betwee .ctors/.dtors and .init_array/.fini_array + * is the ordering, but we don't use prioritization for libcom32, so + * just lump them all together and hope that's okay. + */ . = ALIGN(4); - .preinit_array : { - PROVIDE (__preinit_array_start = .); - *(.preinit_array) - PROVIDE (__preinit_array_end = .); - } - .init_array : { - PROVIDE (__init_array_start = .); - *(.init_array) - PROVIDE (__init_array_end = .); - } - .fini_array : { - PROVIDE (__fini_array_start = .); - *(.fini_array) - PROVIDE (__fini_array_end = .); - } .ctors : { PROVIDE (__ctors_start = .); - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) + KEEP (*(SORT(.preinit_array*))) + KEEP (*(SORT(.init_array*))) + KEEP (*(SORT(.ctors*))) PROVIDE (__ctors_end = .); } .dtors : { PROVIDE (__dtors_start = .); - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) + KEEP (*(SORT(.fini_array*))) + KEEP (*(SORT(.dtors*))) PROVIDE (__dtors_end = .); } diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c index 45cd6965..856141f8 100644 --- a/com32/lib/syslinux/load_linux.c +++ b/com32/lib/syslinux/load_linux.c @@ -38,6 +38,7 @@ #include <inttypes.h> #include <string.h> #include <minmax.h> +#include <errno.h> #include <suffix_number.h> #include <syslinux/align.h> #include <syslinux/linux.h> @@ -180,13 +181,16 @@ static int map_initramfs(struct syslinux_movelist **fraglist, } int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, - struct initramfs *initramfs, char *cmdline) + struct initramfs *initramfs, + struct setup_data *setup_data, + char *cmdline) { struct linux_header hdr, *whdr; size_t real_mode_size, prot_mode_size; addr_t real_mode_base, prot_mode_base; addr_t irf_size; size_t cmdline_size, cmdline_offset; + struct setup_data *sdp; struct syslinux_rm_regs regs; struct syslinux_movelist *fraglist = NULL; struct syslinux_memmap *mmap = NULL; @@ -449,6 +453,49 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, } } + if (setup_data) { + uint64_t *prev_ptr = &whdr->setup_data; + + for (sdp = setup_data->next; sdp != setup_data; sdp = sdp->next) { + struct syslinux_memmap *ml; + const addr_t align_mask = 15; /* Header is 16 bytes */ + addr_t best_addr = 0; + size_t size = sdp->hdr.len + sizeof(sdp->hdr); + + if (!sdp->data || !sdp->hdr.len) + continue; + + if (hdr.version < 0x0209) { + /* Setup data not supported */ + errno = ENXIO; /* Kind of arbitrary... */ + goto bail; + } + + for (ml = amap; ml->type != SMT_END; ml = ml->next) { + addr_t adj_start = (ml->start + align_mask) & ~align_mask; + addr_t adj_end = ml->next->start & ~align_mask; + + if (ml->type == SMT_FREE && adj_end - adj_start >= size) + best_addr = (adj_end - size) & ~align_mask; + } + + if (!best_addr) + goto bail; + + *prev_ptr = best_addr; + prev_ptr = &sdp->hdr.next; + + if (syslinux_add_memmap(&amap, best_addr, size, SMT_ALLOC)) + goto bail; + if (syslinux_add_movelist(&fraglist, best_addr, + (addr_t)&sdp->hdr, sizeof sdp->hdr)) + goto bail; + if (syslinux_add_movelist(&fraglist, best_addr + sizeof sdp->hdr, + (addr_t)sdp->data, sdp->hdr.len)) + goto bail; + } + } + /* Set up the registers on entry */ memset(®s, 0, sizeof regs); regs.es = regs.ds = regs.ss = regs.fs = regs.gs = real_mode_base >> 4; diff --git a/com32/lib/syslinux/setup_data.c b/com32/lib/syslinux/setup_data.c new file mode 100644 index 00000000..a36c5b61 --- /dev/null +++ b/com32/lib/syslinux/setup_data.c @@ -0,0 +1,47 @@ +#include <stdlib.h> +#include <syslinux/linux.h> +#include <syslinux/loadfile.h> + +struct setup_data *setup_data_init(void) +{ + struct setup_data *setup_data; + + setup_data = zalloc(sizeof(*setup_data)); + if (!setup_data) + return NULL; + + setup_data->prev = setup_data->next = setup_data; + return setup_data; +} + +int setup_data_add(struct setup_data *head, uint32_t type, + const void *data, size_t data_len) +{ + struct setup_data *setup_data; + + setup_data = zalloc(sizeof(*setup_data)); + if (!setup_data) + return -1; + + setup_data->data = data; + setup_data->hdr.len = data_len; + setup_data->hdr.type = type; + setup_data->prev = head->prev; + setup_data->next = head; + head->prev->next = setup_data; + head->prev = setup_data; + + return 0; +} + +int setup_data_load(struct setup_data *head, uint32_t type, + const char *filename) +{ + void *data; + size_t len; + + if (loadfile(filename, &data, &len)) + return -1; + + return setup_data_add(head, type, data, len); +} diff --git a/com32/lua/src/cpu.c b/com32/lua/src/cpu.c index 8a246e3d..6ef4e5a3 100644 --- a/com32/lua/src/cpu.c +++ b/com32/lua/src/cpu.c @@ -9,13 +9,13 @@ #include"lualib.h" #include"cpuid.h" -static void add_string_item(lua_State *L, const char *item, const char *value_str) { +void add_string_item(lua_State *L, const char *item, const char *value_str) { lua_pushstring(L,item); lua_pushstring(L,value_str); lua_settable(L,-3); } -static void add_int_item(lua_State *L, const char *item, int value_int) { +void add_int_item(lua_State *L, const char *item, int value_int) { lua_pushstring(L,item); lua_pushnumber(L,value_int); lua_settable(L,-3); diff --git a/com32/lua/src/dmi.c b/com32/lua/src/dmi.c index c8329d33..984fb60c 100644 --- a/com32/lua/src/dmi.c +++ b/com32/lua/src/dmi.c @@ -9,275 +9,487 @@ #include "lualib.h" #include "dmi/dmi.h" -static int dmi_gettable(lua_State *L) +extern void add_string_item(lua_State*, const char*, const char*); +extern void add_int_item(lua_State*, const char*, int); +typedef int (*table_fn)(lua_State*, s_dmi*); + +/* Add a Lua_String entry to the table on stack + xxx_P is the poiter version (i.e., pBase is a pointer) + xxx_S is the staic version (i.e., Base is the struct) +*/ +#define LUA_ADD_STR_P(pLua_state, pBase, Field) \ + add_string_item(pLua_state, #Field, pBase->Field); +#define LUA_ADD_STR_S(pLua_state, Base, Field) \ + add_string_item(pLua_state, #Field, Base.Field); + +/* Add a Lua_Number entry to the table on stack + xxx_P is the poiter version (i.e., pBase is a pointer) + xxx_S is the staic version (i.e., Base is the struct) +*/ +#define LUA_ADD_NUM_P(pLua_state, pBase, Field) \ + add_int_item(pLua_state, #Field, pBase->Field); +#define LUA_ADD_NUM_S(pLua_state, Base, Field) \ + add_int_item(pLua_state, #Field, Base.Field); + +/* Add a sub-DMI table to the table on stack + All (*table_fn)() have to be named as get_<tabel_name>_table() for this + macro to work. For example, for the bios subtable, the table_fn is + get_bios_table() and the subtable name is "bios". + All (*table_fn)() have to return 1 if a subtable is created on the stack + or 0 if the subtable is not created (no corresponding dim subtable found). +*/ +#define LUA_ADD_TABLE(pLua_state, pDmi, tb_name) \ + add_dmi_sub_table(pLua_state, pDmi, #tb_name, get_ ## tb_name ## _table); + + +static void add_dmi_sub_table(lua_State *L, s_dmi *dmi_ptr, char *table_name, + table_fn get_table_fn) { - s_dmi dmi; - - lua_newtable(L); - - if ( ! dmi_iterate(&dmi) ) { - printf("No DMI Structure found\n"); - return -1; + if (get_table_fn(L, dmi_ptr)) { /* only adding it when it is there */ + lua_pushstring(L, table_name); + lua_insert(L, -2); + lua_settable(L,-3); } +} - parse_dmitable(&dmi); - - /* bios */ - lua_pushstring(L, "bios.vendor"); - lua_pushstring(L, dmi.bios.vendor); - lua_settable(L,-3); - - lua_pushstring(L, "bios.version"); - lua_pushstring(L, dmi.bios.version); - lua_settable(L,-3); - - lua_pushstring(L, "bios.release_date"); - lua_pushstring(L, dmi.bios.release_date); - lua_settable(L,-3); - lua_pushstring(L, "bios.bios_revision"); - lua_pushstring(L, dmi.bios.bios_revision); - lua_settable(L,-3); +void get_bool_table(lua_State *L, const char *str_table[], int n_elem, + bool *bool_table) +{ + int i; + for (i = 0; i < n_elem; i++) { + if (!str_table[i] || !*str_table[i]) /* aviod NULL/empty string */ + continue; + + lua_pushstring(L, str_table[i]); + lua_pushboolean(L, bool_table[i]); + lua_settable(L,-3); + } +} - lua_pushstring(L, "bios.firmware_revision"); - lua_pushstring(L, dmi.bios.firmware_revision); - lua_settable(L,-3); - lua_pushstring(L, "bios.address"); - lua_pushnumber(L, dmi.bios.address); - lua_settable(L,-3); +/* +** {====================================================== +** DMI subtables +** ======================================================= +*/ +static int get_bios_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_bios *bios = &dmi_ptr->bios; - lua_pushstring(L, "bios.runtime_size"); - lua_pushnumber(L, dmi.bios.runtime_size); + if (!bios->filled) + return 0; + /* bios */ + lua_newtable(L); + LUA_ADD_STR_P(L, bios, vendor) + LUA_ADD_STR_P(L, bios, version) + LUA_ADD_STR_P(L, bios, release_date) + LUA_ADD_STR_P(L, bios, bios_revision) + LUA_ADD_STR_P(L, bios, firmware_revision) + LUA_ADD_NUM_P(L, bios, address) + LUA_ADD_NUM_P(L, bios, runtime_size) + LUA_ADD_STR_P(L, bios, runtime_size_unit) + LUA_ADD_NUM_P(L, bios, rom_size) + LUA_ADD_STR_P(L, bios, rom_size_unit) + + /* bios characteristics */ + lua_pushstring(L, "chars"); + lua_newtable(L); + get_bool_table(L, bios_charac_strings, + sizeof(s_characteristics)/sizeof(bool), + (bool *)(&bios->characteristics)); + get_bool_table(L, bios_charac_x1_strings, + sizeof(s_characteristics_x1)/sizeof(bool), + (bool *)(&bios->characteristics_x1)); + get_bool_table(L, bios_charac_x2_strings, + sizeof(s_characteristics_x2)/sizeof(bool), + (bool *)(&bios->characteristics_x2)); lua_settable(L,-3); - lua_pushstring(L, "bios.runtime_size_unit"); - lua_pushstring(L, dmi.bios.runtime_size_unit); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "bios.rom_size"); - lua_pushnumber(L, dmi.bios.rom_size); - lua_settable(L,-3); - lua_pushstring(L, "bios.rom_size_unit"); - lua_pushstring(L, dmi.bios.rom_size_unit); - lua_settable(L,-3); +static int get_system_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_system *system = &dmi_ptr->system; + if (!system->filled) + return 0; /* system */ - lua_pushstring(L, "system.manufacturer"); - lua_pushstring(L, dmi.system.manufacturer); - lua_settable(L,-3); - - lua_pushstring(L, "system.product_name"); - lua_pushstring(L, dmi.system.product_name); - lua_settable(L,-3); - - lua_pushstring(L, "system.version"); - lua_pushstring(L, dmi.system.version); - lua_settable(L,-3); - - lua_pushstring(L, "system.serial"); - lua_pushstring(L, dmi.system.serial); - lua_settable(L,-3); - - lua_pushstring(L, "system.uuid"); - lua_pushstring(L, dmi.system.uuid); - lua_settable(L,-3); + lua_newtable(L); + LUA_ADD_STR_P(L, system, manufacturer) + LUA_ADD_STR_P(L, system, product_name) + LUA_ADD_STR_P(L, system, version) + LUA_ADD_STR_P(L, system, serial) + LUA_ADD_STR_P(L, system, uuid) + LUA_ADD_STR_P(L, system, wakeup_type) + LUA_ADD_STR_P(L, system, sku_number) + LUA_ADD_STR_P(L, system, family) + LUA_ADD_STR_P(L, system, system_boot_status) + LUA_ADD_STR_P(L, system, configuration_options) + + /* system reset */ + if (system->system_reset.filled) { + lua_pushstring(L, "reset"); + lua_newtable(L); + LUA_ADD_NUM_S(L, system->system_reset, status) + LUA_ADD_NUM_S(L, system->system_reset, watchdog) + LUA_ADD_STR_S(L, system->system_reset, boot_option) + LUA_ADD_STR_S(L, system->system_reset, boot_option_on_limit) + LUA_ADD_STR_S(L, system->system_reset, reset_count) + LUA_ADD_STR_S(L, system->system_reset, reset_limit) + LUA_ADD_STR_S(L, system->system_reset, timer_interval) + LUA_ADD_STR_S(L, system->system_reset, timeout) + lua_settable(L,-3); + } - lua_pushstring(L, "system.wakeup_type"); - lua_pushstring(L, dmi.system.wakeup_type); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "system.sku_number"); - lua_pushstring(L, dmi.system.sku_number); - lua_settable(L,-3); - lua_pushstring(L, "system.family"); - lua_pushstring(L, dmi.system.family); - lua_settable(L,-3); +static int get_base_board_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_base_board *base_board = &dmi_ptr->base_board; + int n_dev = sizeof(base_board->devices_information) / + sizeof(base_board->devices_information[0]); + int i, j, has_dev; + if (!base_board->filled) + return 0; /* base_board */ - lua_pushstring(L, "base_board.manufacturer"); - lua_pushstring(L, dmi.base_board.manufacturer); - lua_settable(L,-3); - - lua_pushstring(L, "base_board.product_name"); - lua_pushstring(L, dmi.base_board.product_name); - lua_settable(L,-3); + lua_newtable(L); + LUA_ADD_STR_P(L, base_board, manufacturer) + LUA_ADD_STR_P(L, base_board, product_name) + LUA_ADD_STR_P(L, base_board, version) + LUA_ADD_STR_P(L, base_board, serial) + LUA_ADD_STR_P(L, base_board, asset_tag) + LUA_ADD_STR_P(L, base_board, location) + LUA_ADD_STR_P(L, base_board, type) + + /* base board features */ + lua_pushstring(L, "features"); + lua_newtable(L); + get_bool_table(L, base_board_features_strings, + sizeof(s_base_board_features)/sizeof(bool), + (bool *)(&base_board->features)); + lua_settable(L,-3); + + /* on-board devices */ + for (has_dev = 0, i = 0; i < n_dev; i++) + if (*base_board->devices_information[i].type) + has_dev++; + + if (has_dev) { + lua_pushstring(L, "devices"); + lua_newtable(L); + for (i = 0, j = 1; i < n_dev; i++) { + if (!*base_board->devices_information[i].type) /* empty device */ + continue; + + lua_pushinteger(L, j++); + lua_newtable(L); + LUA_ADD_STR_S(L, base_board->devices_information[i], type) + LUA_ADD_STR_S(L, base_board->devices_information[i], description) + LUA_ADD_NUM_S(L, base_board->devices_information[i], status) + lua_settable(L,-3); + } + lua_settable(L,-3); + } - lua_pushstring(L, "base_board.version"); - lua_pushstring(L, dmi.base_board.version); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "base_board.serial"); - lua_pushstring(L, dmi.base_board.serial); - lua_settable(L,-3); - lua_pushstring(L, "base_board.asset_tag"); - lua_pushstring(L, dmi.base_board.asset_tag); - lua_settable(L,-3); +static int get_chassis_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_chassis *chassis = &dmi_ptr->chassis; - lua_pushstring(L, "base_board.location"); - lua_pushstring(L, dmi.base_board.location); - lua_settable(L,-3); + if (!chassis->filled) + return 0; + /* chassis */ + lua_newtable(L); + LUA_ADD_STR_P(L, chassis, manufacturer) + LUA_ADD_STR_P(L, chassis, type) + LUA_ADD_STR_P(L, chassis, lock) + LUA_ADD_STR_P(L, chassis, version) + LUA_ADD_STR_P(L, chassis, serial) + LUA_ADD_STR_P(L, chassis, asset_tag) + LUA_ADD_STR_P(L, chassis, boot_up_state) + LUA_ADD_STR_P(L, chassis, power_supply_state) + LUA_ADD_STR_P(L, chassis, thermal_state) + LUA_ADD_STR_P(L, chassis, security_status) + LUA_ADD_STR_P(L, chassis, oem_information) + LUA_ADD_NUM_P(L, chassis, height) + LUA_ADD_NUM_P(L, chassis, nb_power_cords) - lua_pushstring(L, "base_board.type"); - lua_pushstring(L, dmi.base_board.type); - lua_settable(L,-3); + return 1; +} - /* chassis */ - lua_pushstring(L, "chassis.manufacturer"); - lua_pushstring(L, dmi.chassis.manufacturer); - lua_settable(L,-3); - lua_pushstring(L, "chassis.type"); - lua_pushstring(L, dmi.chassis.type); - lua_settable(L,-3); +static int get_processor_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_processor *processor = &dmi_ptr->processor; + s_signature *signature = &processor->signature; - lua_pushstring(L, "chassis.lock"); - lua_pushstring(L, dmi.chassis.lock); + if (!processor->filled) + return 0; + /* processor */ + lua_newtable(L); + LUA_ADD_STR_P(L, processor, socket_designation) + LUA_ADD_STR_P(L, processor, type) + LUA_ADD_STR_P(L, processor, family) + LUA_ADD_STR_P(L, processor, manufacturer) + LUA_ADD_STR_P(L, processor, version) + LUA_ADD_NUM_P(L, processor, external_clock) + LUA_ADD_NUM_P(L, processor, max_speed) + LUA_ADD_NUM_P(L, processor, current_speed) + LUA_ADD_NUM_P(L, processor, voltage_mv) + LUA_ADD_STR_P(L, processor, status) + LUA_ADD_STR_P(L, processor, upgrade) + LUA_ADD_STR_P(L, processor, cache1) + LUA_ADD_STR_P(L, processor, cache2) + LUA_ADD_STR_P(L, processor, cache3) + LUA_ADD_STR_P(L, processor, serial) + LUA_ADD_STR_P(L, processor, part_number) + LUA_ADD_STR_P(L, processor, id) + LUA_ADD_NUM_P(L, processor, core_count) + LUA_ADD_NUM_P(L, processor, core_enabled) + LUA_ADD_NUM_P(L, processor, thread_count) + + /* processor signature */ + lua_pushstring(L, "signature"); + lua_newtable(L); + LUA_ADD_NUM_P(L, signature, type) + LUA_ADD_NUM_P(L, signature, family) + LUA_ADD_NUM_P(L, signature, model) + LUA_ADD_NUM_P(L, signature, stepping) + LUA_ADD_NUM_P(L, signature, minor_stepping) lua_settable(L,-3); - lua_pushstring(L, "chassis.version"); - lua_pushstring(L, dmi.chassis.version); + /* processor flags */ + lua_pushstring(L, "flags"); + lua_newtable(L); + get_bool_table(L, cpu_flags_strings, + sizeof(s_dmi_cpu_flags)/sizeof(bool), + (bool *)(&processor->cpu_flags)); lua_settable(L,-3); - lua_pushstring(L, "chassis.serial"); - lua_pushstring(L, dmi.chassis.serial); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "chassis.asset_tag"); - lua_pushstring(L, dmi.chassis.asset_tag); - lua_settable(L,-3); - lua_pushstring(L, "chassis.boot_up_state"); - lua_pushstring(L, dmi.chassis.boot_up_state); - lua_settable(L,-3); +static int get_battery_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_battery *battery = &dmi_ptr->battery; - lua_pushstring(L, "chassis.power_supply_state"); - lua_pushstring(L, dmi.chassis.power_supply_state); - lua_settable(L,-3); + if (!battery->filled) + return 0; + /* battery */ + lua_newtable(L); + LUA_ADD_STR_P(L, battery, location) + LUA_ADD_STR_P(L, battery, manufacturer) + LUA_ADD_STR_P(L, battery, manufacture_date) + LUA_ADD_STR_P(L, battery, serial) + LUA_ADD_STR_P(L, battery, name) + LUA_ADD_STR_P(L, battery, chemistry) + LUA_ADD_STR_P(L, battery, design_capacity) + LUA_ADD_STR_P(L, battery, design_voltage) + LUA_ADD_STR_P(L, battery, sbds) + LUA_ADD_STR_P(L, battery, sbds_serial) + LUA_ADD_STR_P(L, battery, maximum_error) + LUA_ADD_STR_P(L, battery, sbds_manufacture_date) + LUA_ADD_STR_P(L, battery, sbds_chemistry) + LUA_ADD_STR_P(L, battery, oem_info) - lua_pushstring(L, "chassis.thermal_state"); - lua_pushstring(L, dmi.chassis.thermal_state); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "chassis.security_status"); - lua_pushstring(L, dmi.chassis.security_status); - lua_settable(L,-3); - lua_pushstring(L, "chassis.oem_information"); - lua_pushstring(L, dmi.chassis.oem_information); - lua_settable(L,-3); +static int get_memory_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_memory *memory = dmi_ptr->memory; + int i, j, n_mem = dmi_ptr->memory_count; - lua_pushstring(L, "chassis.height"); - lua_pushnumber(L, dmi.chassis.height); - lua_settable(L,-3); + if (n_mem <= 0) /* no memory info */ + return 0; - lua_pushstring(L, "chassis.nb_power_cords"); - lua_pushnumber(L, dmi.chassis.nb_power_cords); - lua_settable(L,-3); + /* memory */ + lua_newtable(L); + for (j = 1, i = 0; i < n_mem; i++) { + if (!memory[i].filled) + continue; + + lua_pushinteger(L, j++); + lua_newtable(L); + LUA_ADD_STR_S(L, memory[i], manufacturer) + LUA_ADD_STR_S(L, memory[i], error) + LUA_ADD_STR_S(L, memory[i], total_width) + LUA_ADD_STR_S(L, memory[i], data_width) + LUA_ADD_STR_S(L, memory[i], size) + LUA_ADD_STR_S(L, memory[i], form_factor) + LUA_ADD_STR_S(L, memory[i], device_set) + LUA_ADD_STR_S(L, memory[i], device_locator) + LUA_ADD_STR_S(L, memory[i], bank_locator) + LUA_ADD_STR_S(L, memory[i], type) + LUA_ADD_STR_S(L, memory[i], type_detail) + LUA_ADD_STR_S(L, memory[i], speed) + LUA_ADD_STR_S(L, memory[i], serial) + LUA_ADD_STR_S(L, memory[i], asset_tag) + LUA_ADD_STR_S(L, memory[i], part_number) + lua_settable(L,-3); + } + return 1; +} - /* processor */ - lua_pushstring(L, "processor.socket_designation"); - lua_pushstring(L, dmi.processor.socket_designation); - lua_settable(L,-3); - lua_pushstring(L, "processor.type"); - lua_pushstring(L, dmi.processor.type); - lua_settable(L,-3); +static int get_memory_module_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_memory_module *memory_module = dmi_ptr->memory_module; + int i, j, n_mem = dmi_ptr->memory_module_count; - lua_pushstring(L, "processor.family"); - lua_pushstring(L, dmi.processor.family); - lua_settable(L,-3); + if (n_mem <= 0) /* no memory module info */ + return 0; - lua_pushstring(L, "processor.manufacturer"); - lua_pushstring(L, dmi.processor.manufacturer); - lua_settable(L,-3); + /* memory module */ + lua_newtable(L); + for (j = 1, i = 0; i < n_mem; i++) { + if (!memory_module[i].filled) + continue; + + lua_pushinteger(L, j++); + lua_newtable(L); + LUA_ADD_STR_S(L, memory_module[i], socket_designation) + LUA_ADD_STR_S(L, memory_module[i], bank_connections) + LUA_ADD_STR_S(L, memory_module[i], speed) + LUA_ADD_STR_S(L, memory_module[i], type) + LUA_ADD_STR_S(L, memory_module[i], installed_size) + LUA_ADD_STR_S(L, memory_module[i], enabled_size) + LUA_ADD_STR_S(L, memory_module[i], error_status) + lua_settable(L,-3); + } + return 1; +} - lua_pushstring(L, "processor.version"); - lua_pushstring(L, dmi.processor.version); - lua_settable(L,-3); - lua_pushstring(L, "processor.external_clock"); - lua_pushnumber(L, dmi.processor.external_clock); - lua_settable(L,-3); +static int get_cache_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_cache *cache = dmi_ptr->cache; + int i, n_cache = dmi_ptr->cache_count; - lua_pushstring(L, "processor.max_speed"); - lua_pushnumber(L, dmi.processor.max_speed); - lua_settable(L,-3); + if (n_cache <= 0) /* no cache info */ + return 0; - lua_pushstring(L, "processor.current_speed"); - lua_pushnumber(L, dmi.processor.current_speed); - lua_settable(L,-3); + /* memory */ + lua_newtable(L); + for (i = 0; i < n_cache; i++) { + lua_pushinteger(L, i + 1); + lua_newtable(L); + LUA_ADD_STR_S(L, cache[i], socket_designation) + LUA_ADD_STR_S(L, cache[i], configuration) + LUA_ADD_STR_S(L, cache[i], mode) + LUA_ADD_STR_S(L, cache[i], location) + LUA_ADD_NUM_S(L, cache[i], installed_size) + LUA_ADD_NUM_S(L, cache[i], max_size) + LUA_ADD_STR_S(L, cache[i], supported_sram_types) + LUA_ADD_STR_S(L, cache[i], installed_sram_types) + LUA_ADD_NUM_S(L, cache[i], speed) + LUA_ADD_STR_S(L, cache[i], error_correction_type) + LUA_ADD_STR_S(L, cache[i], system_type) + LUA_ADD_STR_S(L, cache[i], associativity) + lua_settable(L,-3); + } + return 1; +} - lua_pushstring(L, "processor.signature.type"); - lua_pushnumber(L, dmi.processor.signature.type); - lua_settable(L,-3); - lua_pushstring(L, "processor.signature.family"); - lua_pushnumber(L, dmi.processor.signature.family); - lua_settable(L,-3); +static int get_hardware_security_table(lua_State *L, s_dmi *dmi_ptr) +{ + if (!dmi_ptr->hardware_security.filled) + return 0; + /* hardware_security */ + lua_newtable(L); + LUA_ADD_STR_S(L, dmi_ptr->hardware_security, power_on_passwd_status) + LUA_ADD_STR_S(L, dmi_ptr->hardware_security, keyboard_passwd_status) + LUA_ADD_STR_S(L, dmi_ptr->hardware_security, administrator_passwd_status) + LUA_ADD_STR_S(L, dmi_ptr->hardware_security, front_panel_reset_status) - lua_pushstring(L, "processor.signature.model"); - lua_pushnumber(L, dmi.processor.signature.model); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "processor.signature.stepping"); - lua_pushnumber(L, dmi.processor.signature.stepping); - lua_settable(L,-3); - lua_pushstring(L, "processor.signature.minor_stepping"); - lua_pushnumber(L, dmi.processor.signature.minor_stepping); - lua_settable(L,-3); +static int get_dmi_info_table(lua_State *L, s_dmi *dmi_ptr) +{ + dmi_table *dmitable = &dmi_ptr->dmitable; - lua_pushstring(L, "processor.voltage_mv"); - lua_pushnumber(L, dmi.processor.voltage_mv); - lua_settable(L,-3); + /* dmi info */ + lua_newtable(L); + LUA_ADD_NUM_P(L, dmitable, num) + LUA_ADD_NUM_P(L, dmitable, len) + LUA_ADD_NUM_P(L, dmitable, ver) + LUA_ADD_NUM_P(L, dmitable, base) + LUA_ADD_NUM_P(L, dmitable, major_version) + LUA_ADD_NUM_P(L, dmitable, minor_version) - lua_pushstring(L, "processor.status"); - lua_pushstring(L, dmi.processor.status); - lua_settable(L,-3); + return 1; +} - lua_pushstring(L, "processor.upgrade"); - lua_pushstring(L, dmi.processor.upgrade); - lua_settable(L,-3); - lua_pushstring(L, "processor.cache1"); - lua_pushstring(L, dmi.processor.cache1); - lua_settable(L,-3); +static int get_ipmi_table(lua_State *L, s_dmi *dmi_ptr) +{ + s_ipmi *ipmi = &dmi_ptr->ipmi; - lua_pushstring(L, "processor.cache2"); - lua_pushstring(L, dmi.processor.cache2); - lua_settable(L,-3); + if (!ipmi->filled) + return 0; + /* ipmi */ + lua_newtable(L); + LUA_ADD_STR_P(L, ipmi, interface_type) + LUA_ADD_NUM_P(L, ipmi, major_specification_version) + LUA_ADD_NUM_P(L, ipmi, minor_specification_version) + LUA_ADD_NUM_P(L, ipmi, I2C_slave_address) + LUA_ADD_NUM_P(L, ipmi, nv_address) + LUA_ADD_NUM_P(L, ipmi, base_address) + LUA_ADD_NUM_P(L, ipmi, irq) - lua_pushstring(L, "processor.cache3"); - lua_pushstring(L, dmi.processor.cache3); - lua_settable(L,-3); + return 1; +} +/* +** {====================================================== +** End of DMI subtables +** ======================================================= +*/ - lua_pushstring(L, "processor.serial"); - lua_pushstring(L, dmi.processor.serial); - lua_settable(L,-3); - lua_pushstring(L, "processor.part_number"); - lua_pushstring(L, dmi.processor.part_number); - lua_settable(L,-3); +static int dmi_gettable(lua_State *L) +{ + s_dmi dmi; - lua_pushstring(L, "processor.id"); - lua_pushstring(L, dmi.processor.id); - lua_settable(L,-3); + lua_newtable(L); - lua_pushstring(L, "processor.core_count"); - lua_pushnumber(L, dmi.processor.core_count); - lua_settable(L,-3); + if ( ! dmi_iterate(&dmi) ) { + printf("No DMI Structure found\n"); + return -1; + } - lua_pushstring(L, "processor.core_enabled"); - lua_pushnumber(L, dmi.processor.core_enabled); - lua_settable(L,-3); + parse_dmitable(&dmi); - lua_pushstring(L, "processor.thread_count"); - lua_pushnumber(L, dmi.processor.thread_count); - lua_settable(L,-3); + LUA_ADD_NUM_S(L, dmi, memory_module_count) + LUA_ADD_NUM_S(L, dmi, memory_count) + LUA_ADD_NUM_S(L, dmi, cache_count) + LUA_ADD_STR_S(L, dmi, oem_strings) + + LUA_ADD_TABLE(L, &dmi, bios) + LUA_ADD_TABLE(L, &dmi, system) + LUA_ADD_TABLE(L, &dmi, base_board) + LUA_ADD_TABLE(L, &dmi, chassis) + LUA_ADD_TABLE(L, &dmi, processor) + LUA_ADD_TABLE(L, &dmi, battery) + LUA_ADD_TABLE(L, &dmi, memory) + LUA_ADD_TABLE(L, &dmi, memory_module) + LUA_ADD_TABLE(L, &dmi, cache) + LUA_ADD_TABLE(L, &dmi, ipmi) + LUA_ADD_TABLE(L, &dmi, hardware_security) + LUA_ADD_TABLE(L, &dmi, dmi_info) /* set global variable: lua_setglobal(L, "dmitable"); */ diff --git a/com32/lua/src/liolib.c b/com32/lua/src/liolib.c index 3f27395d..cf9dca22 100644 --- a/com32/lua/src/liolib.c +++ b/com32/lua/src/liolib.c @@ -18,12 +18,18 @@ #include "lauxlib.h" #include "lualib.h" - +#ifdef SYSLINUX + #define NO_TMP_FILE 1 + #define NO_READ_NUMBER 1 + #define NO_TEST_EOF 1 + #define NO_CLEAR_ERR 1 + #define NO_F_SEEK 1 + #define NO_F_SETVBUF 1 +#endif #define IO_INPUT 1 #define IO_OUTPUT 2 - static const char *const fnames[] = {"input", "output"}; @@ -180,7 +186,7 @@ static int io_popen (lua_State *L) { } -#ifndef SYSLINUX +#ifndef NO_TMP_FILE static int io_tmpfile (lua_State *L) { FILE **pf = newfile(L); *pf = tmpfile(); @@ -271,7 +277,7 @@ static int io_lines (lua_State *L) { ** ======================================================= */ -#ifndef SYSLINUX +#ifndef NO_READ_NUMBER /* No fscanf() and thus no read_number() */ static int read_number (lua_State *L, FILE *f) { lua_Number d; if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { @@ -283,8 +289,9 @@ static int read_number (lua_State *L, FILE *f) { return 0; /* read fails */ } } +#endif - +#ifndef NO_TEST_EOF /* no buffering -> no ungetc() -> no EOF test */ static int test_eof (lua_State *L, FILE *f) { int c = getc(f); ungetc(c, f); @@ -315,7 +322,6 @@ static int read_line (lua_State *L, FILE *f) { } } -#ifndef SYSLINUX /* Not used */ static int read_chars (lua_State *L, FILE *f, size_t n) { size_t rlen; /* how much to read */ size_t nr; /* number of chars actually read */ @@ -337,7 +343,9 @@ static int g_read (lua_State *L, FILE *f, int first) { int nargs = lua_gettop(L) - 1; int success; int n; +#ifndef NO_CLEAR_ERR clearerr(f); +#endif if (nargs == 0) { /* no arguments? */ success = read_line(L, f); n = first+1; /* to return 1 result */ @@ -348,14 +356,22 @@ static int g_read (lua_State *L, FILE *f, int first) { for (n = first; nargs-- && success; n++) { if (lua_type(L, n) == LUA_TNUMBER) { size_t l = (size_t)lua_tointeger(L, n); +#ifndef NO_TEST_EOF success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); +#else /* we don't have test_eof defined */ + success = (l == 0) ? 1 : read_chars(L, f, l); +#endif } else { const char *p = lua_tostring(L, n); luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); switch (p[1]) { case 'n': /* number */ +#ifndef NO_READ_NUMBER success = read_number(L, f); +#else + return luaL_argerror(L, n, "\"*number\" not supported"); +#endif break; case 'l': /* line */ success = read_line(L, f); @@ -388,7 +404,6 @@ static int io_read (lua_State *L) { static int f_read (lua_State *L) { return g_read(L, tofile(L), 2); } -#endif static int io_readline (lua_State *L) { @@ -441,7 +456,7 @@ static int f_write (lua_State *L) { return g_write(L, tofile(L), 2); } -#ifndef SYSLINUX +#ifndef NO_F_SEEK static int f_seek (lua_State *L) { static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; static const char *const modenames[] = {"set", "cur", "end", NULL}; @@ -456,8 +471,9 @@ static int f_seek (lua_State *L) { return 1; } } +#endif - +#ifndef NO_F_SETVBUF static int f_setvbuf (lua_State *L) { static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; static const char *const modenames[] = {"no", "full", "line", NULL}; @@ -488,8 +504,8 @@ static const luaL_Reg iolib[] = { {"open", io_open}, {"output", io_output}, {"popen", io_popen}, -#ifndef SYSLINUX {"read", io_read}, +#ifndef NO_TMP_FILE {"tmpfile", io_tmpfile}, #endif {"type", io_type}, @@ -502,9 +518,11 @@ static const luaL_Reg flib[] = { {"close", io_close}, {"flush", f_flush}, {"lines", f_lines}, -#ifndef SYSLINUX {"read", f_read}, +#ifndef NO_F_SEEK {"seek", f_seek}, +#endif +#ifndef NO_F_SETVBUF {"setvbuf", f_setvbuf}, #endif {"write", f_write}, diff --git a/com32/lua/src/syslinux.c b/com32/lua/src/syslinux.c index 9b207db7..afcdcaad 100644 --- a/com32/lua/src/syslinux.c +++ b/com32/lua/src/syslinux.c @@ -39,6 +39,7 @@ #include "syslinux/loadfile.h" #include "syslinux/linux.h" #include "syslinux/config.h" +#include "syslinux/reboot.h" int __parse_argv(char ***argv, const char *str); @@ -278,7 +279,7 @@ static int sl_boot_linux(lua_State * L) msleep(10000); */ - ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, newcmdline); + ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, NULL, newcmdline); printf("syslinux_boot_linux returned %d\n", ret); @@ -405,7 +406,36 @@ static int sl_boot_it(lua_State * L) (void)mem_limit; return syslinux_boot_linux(kernel->data, kernel->size, - initramfs, (char *)cmdline); + initramfs, NULL, (char *)cmdline); +} + +static int sl_config_file(lua_State * L) +{ + const char *config_file = syslinux_config_file(); + lua_pushstring(L, config_file); + return 1; +} + +static int sl_reboot(lua_State * L) +{ + int warm_boot = luaL_optint(L, 1, 0); + /* explicitly convert it to 1 or 0 */ + warm_boot = warm_boot? 1 : 0; + syslinux_reboot(warm_boot); + return 0; +} + +static int sl_ipappend_strs(lua_State * L) +{ + int i; + const struct syslinux_ipappend_strings *ip_strs = syslinux_ipappend_strings(); + lua_newtable(L); + for (i = 0; i < ip_strs->count; i++) { + lua_pushinteger(L, i + 1); + lua_pushstring(L, ip_strs->ptr[i]); + lua_settable(L,-3); + } + return 1; } static int sl_derivative(lua_State * L) @@ -459,6 +489,9 @@ static const luaL_reg syslinuxlib[] = { {"initramfs_load_archive", sl_initramfs_load_archive}, {"initramfs_add_file", sl_initramfs_add_file}, {"boot_it", sl_boot_it}, + {"config_file", sl_config_file}, + {"ipappend_strs", sl_ipappend_strs}, + {"reboot", sl_reboot}, {"derivative", sl_derivative}, {"version", sl_version}, {NULL, NULL} diff --git a/com32/mboot/mboot.c b/com32/mboot/mboot.c index 35450e03..10e6701c 100644 --- a/com32/mboot/mboot.c +++ b/com32/mboot/mboot.c @@ -198,7 +198,7 @@ int main(int argc, char *argv[]) } if (init_map()) - return 1; /* Failed to allocate intitial map */ + return 1; /* Failed to allocate initial map */ /* * Map the primary image. This should be done before mapping anything diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c index 5b3f6bd1..7c589797 100644 --- a/com32/menu/menumain.c +++ b/com32/menu/menumain.c @@ -958,8 +958,7 @@ static const char *run_menu(void) case KEY_DOWN: case KEY_CTRL('N'): - while (entry < cm->nentries - 1) { - entry++; + while (++entry < cm->nentries) { if (entry >= top + MENU_ROWS) top += MENU_ROWS; if (!is_disabled(cm->menu_entries[entry])) diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c index 0ac2564a..431017f6 100644 --- a/com32/menu/readconfig.c +++ b/com32/menu/readconfig.c @@ -392,7 +392,9 @@ static void record(struct menu *m, struct labeldata *ld, const char *append) break; } - if (ld->menudefault && me->action == MA_CMD) + if (ld->menudefault && (me->action == MA_CMD || + me->action == MA_GOTO || + me->action == MA_GOTO_UNRES)) m->defentry = m->nentries - 1; } diff --git a/com32/modules/Makefile b/com32/modules/Makefile index 35e297fe..f110e584 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -24,7 +24,7 @@ MODULES = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \ kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \ ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 zzjson.c32 \ - whichsys.c32 prdhcp.c32 pxechn.c32 + whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 TESTFILES = diff --git a/com32/modules/kontron_wdt.c b/com32/modules/kontron_wdt.c new file mode 100644 index 00000000..4e1d2535 --- /dev/null +++ b/com32/modules/kontron_wdt.c @@ -0,0 +1,414 @@ +/* + * kempld_wdt.c - Kontron PLD watchdog driver + * + * Copyright (c) 2010 Kontron Embedded Modules GmbH + * Author: Michael Brunner <michael.brunner@kontron.com> + * Author: Erwan Velu <erwan.velu@zodiacaerospace.com> + * + * Note: From the PLD watchdog point of view timeout and pretimeout are + * defined differently than in the kernel. + * First the pretimeout stage runs out before the timeout stage gets + * active. This has to be kept in mind. + * + * Kernel/API: P-----| pretimeout + * |-----------------------T timeout + * Watchdog: |-----------------P pretimeout_stage + * |-----T timeout_stage + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <string.h> +#include <sys/io.h> +#include <unistd.h> +#include <syslinux/boot.h> +#include <stdio.h> +#include <stdlib.h> +#include <console.h> +#include "kontron_wdt.h" + +struct kempld_device_data pld; +struct kempld_watchdog_data wdt; +uint8_t status; +char default_label[255]; + +/* Default Timeout is 60sec */ +#define TIMEOUT 60 +#define PRETIMEOUT 0 + +#define do_div(n,base) ({ \ + int __res; \ + __res = ((unsigned long) n) % (unsigned) base; \ + n = ((unsigned long) n) / (unsigned) base; \ + __res; }) + + +/* Basic Wrappers to get code as less changed as possible */ +void iowrite8(uint8_t val, uint16_t addr) { outb(val,addr); } +void iowrite16(uint16_t val, uint16_t addr) { outw(val,addr); } +void iowrite32(uint32_t val, uint16_t addr) { outl(val,addr);} +uint8_t ioread8(uint16_t addr) { return inb(addr);} +uint16_t ioread16(uint16_t addr) { return inw(addr);} +uint32_t ioread32(uint32_t addr) { return inl(addr);} + + +/** + * kempld_set_index - change the current register index of the PLD + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * This function changes the register index of the PLD. + */ +void kempld_set_index(struct kempld_device_data *pld, uint8_t index) +{ + if (pld->last_index != index) { + iowrite8(index, pld->io_index); + pld->last_index = index; + } +} + + +uint8_t kempld_read8(struct kempld_device_data *pld, uint8_t index) { + kempld_set_index(pld, index); + return ioread8(pld->io_data); +} + + +void kempld_write8(struct kempld_device_data *pld, uint8_t index, uint8_t data) { + kempld_set_index(pld, index); + iowrite8(data, pld->io_data); +} + + +uint16_t kempld_read16(struct kempld_device_data *pld, uint8_t index) +{ + return kempld_read8(pld, index) | kempld_read8(pld, index+1) << 8; +} + + +void kempld_write16(struct kempld_device_data *pld, uint8_t index, uint16_t data) +{ + kempld_write8(pld, index, (uint8_t)data); + kempld_write8(pld, index+1, (uint8_t)(data>>8)); +} + +uint32_t kempld_read32(struct kempld_device_data *pld, uint8_t index) +{ + return kempld_read16(pld, index) | kempld_read16(pld, index+2) << 16; +} + +void kempld_write32(struct kempld_device_data *pld, uint8_t index, uint32_t data) +{ + kempld_write16(pld, index, (uint16_t)data); + kempld_write16(pld, index+2, (uint16_t)(data>>16)); +} + +static void kempld_release_mutex(struct kempld_device_data *pld) +{ + iowrite8(pld->last_index | KEMPLD_MUTEX_KEY, pld->io_index); +} + +void init_structure(void) { + /* set default values for the case we start the watchdog or change + * the configuration */ + memset(&wdt,0,sizeof(wdt)); + memset(&pld,0,sizeof(pld)); + memset(&default_label,0,sizeof(default_label)); + wdt.timeout = TIMEOUT; + wdt.pretimeout = PRETIMEOUT; + wdt.pld = &pld; + + pld.io_base=KEMPLD_IOPORT; + pld.io_index=KEMPLD_IOPORT; + pld.io_data=KEMPLD_IODATA; + pld.pld_clock=33333333; +} + +static int kempld_probe(void) { + /* Check for empty IO space */ + int ret=0; + uint8_t index_reg = ioread8(pld.io_index); + if ((index_reg == 0xff) && (ioread8(pld.io_data) == 0xff)) { + ret = 1; + goto err_empty_io; + } + printf("Kempld structure found at 0x%X (data @ 0x%X)\n",pld.io_base,pld.io_data); + return 0; + +err_empty_io: + printf("No IO Found !\n"); + return ret; +} + +static int kempld_wdt_probe_stages(struct kempld_watchdog_data *wdt) +{ + struct kempld_device_data *pld = wdt->pld; + int i, ret; + uint32_t timeout; + uint32_t timeout_mask; + struct kempld_watchdog_stage *stage; + + wdt->stages = 0; + wdt->timeout_stage = NULL; + wdt->pretimeout_stage = NULL; + + for (i = 0; i < KEMPLD_WDT_MAX_STAGES; i++) { + + timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(i)); + kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(i), 0x00000000); + timeout_mask = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(i)); + kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(i), timeout); + + if (timeout_mask != 0xffffffff) { + stage = malloc(sizeof(struct kempld_watchdog_stage)); + if (stage == NULL) { + ret = -1; + goto err_alloc_stages; + } + stage->num = i; + stage->timeout_mask = ~timeout_mask; + wdt->stage[i] = stage; + wdt->stages++; + + /* assign available stages to timeout and pretimeout */ + if (wdt->stages == 1) + wdt->timeout_stage = stage; + else if (wdt->stages == 2) { + wdt->pretimeout_stage = wdt->timeout_stage; + wdt->timeout_stage = stage; + } + } else { + wdt->stage[i] = NULL; + } + } + + return 0; +err_alloc_stages: + kempld_release_mutex(pld); + printf("Cannot allocate stages\n"); + return ret; +} + +static int kempld_wdt_keepalive(struct kempld_watchdog_data *wdt) +{ + struct kempld_device_data *pld = wdt->pld; + + kempld_write8(pld, KEMPLD_WDT_KICK, 'K'); + + return 0; +} + +static int kempld_wdt_setstageaction(struct kempld_watchdog_data *wdt, + struct kempld_watchdog_stage *stage, + int action) +{ + struct kempld_device_data *pld = wdt->pld; + uint8_t stage_cfg; + + if (stage == NULL) + return -1; + + stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->num)); + stage_cfg &= ~KEMPLD_WDT_STAGE_CFG_ACTION_MASK; + stage_cfg |= (action & KEMPLD_WDT_STAGE_CFG_ACTION_MASK); + if (action == KEMPLD_WDT_ACTION_RESET) + stage_cfg |= KEMPLD_WDT_STAGE_CFG_ASSERT; + else + stage_cfg &= ~KEMPLD_WDT_STAGE_CFG_ASSERT; + + kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->num), stage_cfg); + stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->num)); + + return 0; +} + +static int kempld_wdt_setstagetimeout(struct kempld_watchdog_data *wdt, + struct kempld_watchdog_stage *stage, + int timeout) +{ + struct kempld_device_data *pld = wdt->pld; + uint8_t stage_cfg; + uint8_t prescaler; + uint64_t stage_timeout64; + uint32_t stage_timeout; + + if (stage == NULL) + return -1; + + prescaler = KEMPLD_WDT_PRESCALER_21BIT; + + stage_timeout64 = ((uint64_t)timeout*pld->pld_clock); + do_div(stage_timeout64, KEMPLD_PRESCALER(prescaler)); + stage_timeout = stage_timeout64 & stage->timeout_mask; + + if (stage_timeout64 != (uint64_t)stage_timeout) + return -1; + + stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->num)); + stage_cfg &= ~KEMPLD_WDT_STAGE_CFG_PRESCALER_MASK; + stage_cfg |= KEMPLD_WDT_STAGE_CFG_SET_PRESCALER(prescaler); + kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->num), stage_cfg); + kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->num), + stage_timeout); + + return 0; +} + + +static int kempld_wdt_settimeout(struct kempld_watchdog_data *wdt) +{ + int stage_timeout; + int stage_pretimeout; + int ret; + if ((wdt->timeout <= 0) || + (wdt->pretimeout < 0) || + (wdt->pretimeout > wdt->timeout)) { + ret = -1; + goto err_check_values; + } + + if ((wdt->pretimeout == 0) || (wdt->pretimeout_stage == NULL)) { + if (wdt->pretimeout != 0) + printf("No pretimeout stage available, only enabling reset!\n"); + stage_pretimeout = 0; + stage_timeout = wdt->timeout; + } else { + stage_pretimeout = wdt->timeout - wdt->pretimeout; + stage_timeout = wdt->pretimeout; + } + + if (stage_pretimeout != 0) { + ret = kempld_wdt_setstageaction(wdt, wdt->pretimeout_stage, + KEMPLD_WDT_ACTION_NMI); + } else if ((stage_pretimeout == 0) + && (wdt->pretimeout_stage != NULL)) { + ret = kempld_wdt_setstageaction(wdt, wdt->pretimeout_stage, + KEMPLD_WDT_ACTION_NONE); + } else + ret = 0; + if (ret) + goto err_setstage; + + if (stage_pretimeout != 0) { + ret = kempld_wdt_setstagetimeout(wdt, wdt->pretimeout_stage, + stage_pretimeout); + if (ret) + goto err_setstage; + } + + ret = kempld_wdt_setstageaction(wdt, wdt->timeout_stage, + KEMPLD_WDT_ACTION_RESET); + if (ret) + goto err_setstage; + + ret = kempld_wdt_setstagetimeout(wdt, wdt->timeout_stage, + stage_timeout); + if (ret) + goto err_setstage; + + return 0; +err_setstage: +err_check_values: + return ret; +} + +static int kempld_wdt_start(struct kempld_watchdog_data *wdt) +{ + struct kempld_device_data *pld = wdt->pld; + uint8_t status; + + status = kempld_read8(pld, KEMPLD_WDT_CFG); + status |= KEMPLD_WDT_CFG_ENABLE; + kempld_write8(pld, KEMPLD_WDT_CFG, status); + status = kempld_read8(pld, KEMPLD_WDT_CFG); + + /* check if the watchdog was enabled */ + if (!(status & KEMPLD_WDT_CFG_ENABLE)) + return -1; + + return 0; +} + +/* A regular configuration file looks like + + LABEL WDT + COM32 wdt.c32 + APPEND timeout=120 default_label=local +*/ +void detect_parameters(const int argc, const char *argv[]) { + for (int i = 1; i < argc; i++) { + /* Override the timeout if specified on the cmdline */ + if (!strncmp(argv[i], "timeout=", 8)) { + wdt.timeout=atoi(argv[i]+8); + } else + /* Define which boot entry shall be used */ + if (!strncmp(argv[i], "default_label=", 14)) { + strlcpy(default_label, argv[i] + 14, sizeof(default_label)); + } + } +} + +int main(int argc, const char *argv[]) { + int ret=0; + openconsole(&dev_rawcon_r, &dev_stdcon_w); + init_structure(); + detect_parameters(argc,argv); + kempld_probe(); + + /* probe how many usable stages we have */ + if (kempld_wdt_probe_stages(&wdt)) { + printf("Cannot Probe Stages\n"); + return -1; + } + + /* Useless but who knows */ + wdt.ident.firmware_version = KEMPLD_WDT_REV_GET(kempld_read8(&pld, KEMPLD_WDT_REV)); + + status = kempld_read8(&pld, KEMPLD_WDT_CFG); + /* kick the watchdog if it is already enabled, otherwise start it */ + if (status & KEMPLD_WDT_CFG_ENABLE) { + /* Maybye the BIOS did setup a first timer + * in this case, let's enforce the timeout + * to be sure we do have the proper value */ + kempld_wdt_settimeout(&wdt); + kempld_wdt_keepalive(&wdt); + } else { + ret = kempld_wdt_settimeout(&wdt); + if (ret) { + printf("Unable to setup timeout !\n"); + goto booting; + } + + ret = kempld_wdt_start(&wdt); + if (ret) { + printf("Unable to start watchdog !\n"); + goto booting; + } + + } + + printf("Watchog armed ! Rebooting in %d seconds if no feed occurs !\n",wdt.timeout); + +booting: + /* Release Mutex to let Linux's Driver taking control */ + kempld_release_mutex(&pld); + + /* Let's boot the default entry if specified */ + if (strlen(default_label)>0) { + printf("Executing default label = '%s'\n",default_label); + syslinux_run_command(default_label); + } else { + return ret; + } +} diff --git a/com32/modules/kontron_wdt.h b/com32/modules/kontron_wdt.h new file mode 100644 index 00000000..e916de30 --- /dev/null +++ b/com32/modules/kontron_wdt.h @@ -0,0 +1,117 @@ +/* + * kempld_wdt.h - Kontron PLD watchdog driver definitions + * + * Copyright (c) 2010 Kontron Embedded Modules GmbH + * Author: Michael Brunner <michael.brunner@kontron.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _KEMPLD_WDT_H_ +#define _KEMPLD_WDT_H_ +#include <stdint.h> + +#define KEMPLD_IOPORT 0x0a80 +#define KEMPLD_IODATA (KEMPLD_IOPORT+1) + +#define KEMPLD_MUTEX_KEY 0x80 + +/* watchdog register definitions */ +#define KEMPLD_WDT_KICK 0x16 +#define KEMPLD_WDT_REV 0x16 +#define KEMPLD_WDT_REV_GET(x) (x & 0xf) +#define KEMPLD_WDT_CFG 0x17 +#define KEMPLD_WDT_CFG_STAGE_TIMEOUT_OCCURED(x) (1<<x) +#define KEMPLD_WDT_CFG_ENABLE_LOCK 0x8 +#define KEMPLD_WDT_CFG_ENABLE 0x10 +#define KEMPLD_WDT_CFG_AUTO_RELOAD 0x40 +#define KEMPLD_WDT_CFG_GLOBAL_LOCK 0x80 +#define KEMPLD_WDT_STAGE_CFG(x) (0x18+x) +#define KEMPLD_WDT_STAGE_CFG_ACTION_MASK 0x7 +#define KEMPLD_WDT_STAGE_CFG_GET_ACTION(x) (x & 0x7) +#define KEMPLD_WDT_STAGE_CFG_ASSERT 0x8 +#define KEMPLD_WDT_STAGE_CFG_PRESCALER_MASK 0x30 +#define KEMPLD_WDT_STAGE_CFG_GET_PRESCALER(x) ((x & 0x30)>>4) +#define KEMPLD_WDT_STAGE_CFG_SET_PRESCALER(x) ((x & 0x30)<<4) +#define KEMPLD_WDT_STAGE_TIMEOUT(x) (0x1b+x*4) +#define KEMPLD_WDT_MAX_STAGES 3 + +#define KEMPLD_WDT_ACTION_NONE 0x0 +#define KEMPLD_WDT_ACTION_RESET 0x1 +#define KEMPLD_WDT_ACTION_NMI 0x2 +#define KEMPLD_WDT_ACTION_SMI 0x3 +#define KEMPLD_WDT_ACTION_SCI 0x4 +#define KEMPLD_WDT_ACTION_DELAY 0x5 + +#define KEMPLD_WDT_PRESCALER_21BIT 0x0 +#define KEMPLD_WDT_PRESCALER_17BIT 0x1 +#define KEMPLD_WDT_PRESCALER_12BIT 0x2 + +const int kempld_prescaler_bits[] = { 21, 17, 12 }; + +struct kempld_watchdog_stage { + int num; + uint32_t timeout_mask; +}; + +/** + * struct kempld_device_data - Internal representation of the PLD device + * @io_base: Pointer to the IO memory + * @io_index: Pointer to the IO index register + * @io_data: Pointer to the IO data register + * @pld_clock: PLD clock frequency + * @lock: PLD spin-lock + * @lock_flags: PLD spin-lock flags + * @have_mutex: Bool value that indicates if mutex is aquired + * @last_index: Last written index value + * @rscr: Kernel resource structure + * @dev: Pointer to kernel device structure + * @info: KEMPLD info structure + */ +struct kempld_device_data { + uint16_t io_base; + uint16_t io_index; + uint16_t io_data; + uint32_t pld_clock; +/* spinlock_t lock; + unsigned long lock_flags; */ + int have_mutex; + uint8_t last_index; +/* struct resource rscr; + struct device *dev; + struct kempld_info info;*/ +}; + +struct watchdog_info { + uint32_t options; /* Options the card/driver supports */ + uint32_t firmware_version; /* Firmware version of the card */ + uint8_t identity[32]; /* Identity of the board */ +}; + +struct kempld_watchdog_data { + unsigned int revision; + int timeout; + int pretimeout; + unsigned long is_open; + unsigned long expect_close; + int stages; + struct kempld_watchdog_stage *timeout_stage; + struct kempld_watchdog_stage *pretimeout_stage; + struct kempld_device_data *pld; + struct kempld_watchdog_stage *stage[KEMPLD_WDT_MAX_STAGES]; + struct watchdog_info ident; +}; + +#endif /* _KEMPLD_WDT_H_ */ +#define KEMPLD_PRESCALER(x) (0xffffffff>>(32-kempld_prescaler_bits[x])) diff --git a/com32/modules/linux.c b/com32/modules/linux.c index b902ebc5..76443f91 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved - * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * Copyright 2009-2012 Intel Corporation; author: H. Peter Anvin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -38,6 +38,7 @@ * Usage: linux.c32 [-dhcpinfo] kernel arguments... */ +#include <errno.h> #include <stdbool.h> #include <stdlib.h> #include <stdio.h> @@ -108,10 +109,31 @@ static char *make_cmdline(char **argv) return cmdline; } +static int setup_data_file(struct setup_data *setup_data, + uint32_t type, const char *filename, + bool opt_quiet) +{ + if (!opt_quiet) + printf("Loading %s... ", filename); + + if (setup_data_load(setup_data, type, filename)) { + if (opt_quiet) + printf("Loading %s ", filename); + printf("failed\n"); + return -1; + } + + if (!opt_quiet) + printf("ok\n"); + + return 0; +} + int main(int argc, char *argv[]) { const char *kernel_name; struct initramfs *initramfs; + struct setup_data *setup_data; char *cmdline; char *boot_image; void *kernel_data; @@ -120,7 +142,7 @@ int main(int argc, char *argv[]) bool opt_quiet = false; void *dhcpdata; size_t dhcplen; - char **argp, *arg, *p; + char **argp, **argl, *arg, *p; openconsole(&dev_null_r, &dev_stdcon_w); @@ -144,9 +166,12 @@ int main(int argc, char *argv[]) kernel_name = arg; + errno = 0; boot_image = malloc(strlen(kernel_name) + 12); - if (!boot_image) + if (!boot_image) { + fprintf(stderr, "Error allocating BOOT_IMAGE string: "); goto bail; + } strcpy(boot_image, "BOOT_IMAGE="); strcpy(boot_image + 11, kernel_name); /* argp now points to the kernel name, and the command line follows. @@ -159,23 +184,30 @@ int main(int argc, char *argv[]) if (!opt_quiet) printf("Loading %s... ", kernel_name); + errno = 0; if (loadfile(kernel_name, &kernel_data, &kernel_len)) { if (opt_quiet) printf("Loading %s ", kernel_name); - printf("failed!\n"); + printf("failed: "); goto bail; } if (!opt_quiet) printf("ok\n"); + errno = 0; cmdline = make_cmdline(argp); - if (!cmdline) + if (!cmdline) { + fprintf(stderr, "make_cmdline() failed: "); goto bail; + } /* Initialize the initramfs chain */ + errno = 0; initramfs = initramfs_init(); - if (!initramfs) + if (!initramfs) { + fprintf(stderr, "initramfs_init() failed: "); goto bail; + } if ((arg = find_argument(argp, "initrd="))) { do { @@ -185,10 +217,11 @@ int main(int argc, char *argv[]) if (!opt_quiet) printf("Loading %s... ", arg); + errno = 0; if (initramfs_load_archive(initramfs, arg)) { if (opt_quiet) printf("Loading %s ", kernel_name); - printf("failed!\n"); + printf("failed: "); goto bail; } if (!opt_quiet) @@ -202,15 +235,57 @@ int main(int argc, char *argv[]) /* Append the DHCP info */ if (opt_dhcpinfo && !pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { + errno = 0; if (initramfs_add_file(initramfs, dhcpdata, dhcplen, dhcplen, - "/dhcpinfo.dat", 0, 0755)) + "/dhcpinfo.dat", 0, 0755)) { + fprintf(stderr, "Unable to add DHCP info: "); goto bail; + } + } + + /* Handle dtb and eventually other setup data */ + setup_data = setup_data_init(); + if (!setup_data) + goto bail; + + for (argl = argv; (arg = *argl); argl++) { + if (!memcmp(arg, "dtb=", 4)) { + if (setup_data_file(setup_data, SETUP_DTB, arg+4, opt_quiet)) + goto bail; + } else if (!memcmp(arg, "blob.", 5)) { + uint32_t type; + char *ep; + + type = strtoul(arg + 5, &ep, 10); + if (ep[0] != '=' || !ep[1]) + continue; + + if (!type) + continue; + + if (setup_data_file(setup_data, type, ep+1, opt_quiet)) + goto bail; + } } /* This should not return... */ - syslinux_boot_linux(kernel_data, kernel_len, initramfs, cmdline); + errno = 0; + syslinux_boot_linux(kernel_data, kernel_len, initramfs, + setup_data, cmdline); + fprintf(stderr, "syslinux_boot_linux() failed: "); bail: - fprintf(stderr, "Kernel load failure (insufficient memory?)\n"); + switch(errno) { + case ENOENT: + fprintf(stderr, "File not found\n"); + break; + case ENOMEM: + fprintf(stderr, "Out of memory\n"); + break; + default: + fprintf(stderr, "Error %d\n", errno); + break; + } + fprintf(stderr, "%s: Boot aborted!\n", progname); return 1; } diff --git a/com32/tools/Makefile b/com32/tools/Makefile index 7badabd2..0161baf1 100644 --- a/com32/tools/Makefile +++ b/com32/tools/Makefile @@ -15,6 +15,8 @@ include $(MAKEDIR)/build.mk BINS = relocs +INCLUDES += -I./include + all : $(BINS) relocs : relocs.o diff --git a/com32/tools/include/tools/le_byteshift.h b/com32/tools/include/tools/le_byteshift.h new file mode 100644 index 00000000..c99d45a6 --- /dev/null +++ b/com32/tools/include/tools/le_byteshift.h @@ -0,0 +1,70 @@ +#ifndef _TOOLS_LE_BYTESHIFT_H +#define _TOOLS_LE_BYTESHIFT_H + +#include <linux/types.h> + +static inline __u16 __get_unaligned_le16(const __u8 *p) +{ + return p[0] | p[1] << 8; +} + +static inline __u32 __get_unaligned_le32(const __u8 *p) +{ + return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; +} + +static inline __u64 __get_unaligned_le64(const __u8 *p) +{ + return (__u64)__get_unaligned_le32(p + 4) << 32 | + __get_unaligned_le32(p); +} + +static inline void __put_unaligned_le16(__u16 val, __u8 *p) +{ + *p++ = val; + *p++ = val >> 8; +} + +static inline void __put_unaligned_le32(__u32 val, __u8 *p) +{ + __put_unaligned_le16(val >> 16, p + 2); + __put_unaligned_le16(val, p); +} + +static inline void __put_unaligned_le64(__u64 val, __u8 *p) +{ + __put_unaligned_le32(val >> 32, p + 4); + __put_unaligned_le32(val, p); +} + +static inline __u16 get_unaligned_le16(const void *p) +{ + return __get_unaligned_le16((const __u8 *)p); +} + +static inline __u32 get_unaligned_le32(const void *p) +{ + return __get_unaligned_le32((const __u8 *)p); +} + +static inline __u64 get_unaligned_le64(const void *p) +{ + return __get_unaligned_le64((const __u8 *)p); +} + +static inline void put_unaligned_le16(__u16 val, void *p) +{ + __put_unaligned_le16(val, p); +} + +static inline void put_unaligned_le32(__u32 val, void *p) +{ + __put_unaligned_le32(val, p); +} + +static inline void put_unaligned_le64(__u64 val, void *p) +{ + __put_unaligned_le64(val, p); +} + +#endif /* _TOOLS_LE_BYTESHIFT_H */ diff --git a/com32/tools/relocs.c b/com32/tools/relocs.c index 24742060..86fc7c50 100644 --- a/com32/tools/relocs.c +++ b/com32/tools/relocs.c @@ -13,12 +13,16 @@ #define USE_BSD #include <endian.h> #include <regex.h> -#include <sys/types.h> +#include <tools/le_byteshift.h> + +static void die(char *fmt, ...); #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static Elf32_Ehdr ehdr; static unsigned long reloc_count, reloc_idx; static unsigned long *relocs; +static unsigned long reloc16_count, reloc16_idx; +static unsigned long *relocs16; struct section { Elf32_Shdr shdr; @@ -29,60 +33,87 @@ struct section { }; static struct section *secs; -static void die(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - exit(1); -} +enum symtype { + S_ABS, + S_REL, + S_SEG, + S_LIN, + S_NSYMTYPES +}; +static const char * const sym_regex_kernel[S_NSYMTYPES] = { /* * Following symbols have been audited. Don't warn user about * absolute relocations present w.r.t these symbols. */ + [S_ABS] = + "^(__.*_len|__.*_dwords)$", -/* True absolute relocations */ +/* + * These symbols are known to be relative, even if the linker marks them + * as absolute (typically defined outside any section in the linker script.) + */ + [S_REL] = + "^(__.*_start|__.*_end|_end|_[se](text|data))$", +}; -static const char safe_abs_regex[] = -"^(__.*_len|__.*_dwords)$"; -static regex_t safe_abs_regex_c; -static int is_safe_abs_reloc(const char *sym_name) -{ - return !regexec(&safe_abs_regex_c, sym_name, 0, NULL, 0); -} +static const char * const sym_regex_realmode[S_NSYMTYPES] = { +/* + * These are 16-bit segment symbols when compiling 16-bit code. + */ + [S_SEG] = + "^real_mode_seg$", -/* These are relative even though the linker marks them absolute */ +/* + * These are offsets belonging to segments, as opposed to linear addresses, + * when compiling 16-bit code. + */ + [S_LIN] = + "^pa_", +}; -static const char safe_rel_regex[] = -"^(__.*_start|__.*_end|_end|_[se](text|data))$"; -static regex_t safe_rel_regex_c; +static const char * const *sym_regex; -static int is_safe_rel_reloc(const char *sym_name) +static regex_t sym_regex_c[S_NSYMTYPES]; +static int is_reloc(enum symtype type, const char *sym_name) { - return !regexec(&safe_rel_regex_c, sym_name, 0, NULL, 0); + return sym_regex[type] && + !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0); } -static void regex_init(void) +static void regex_init(int use_real_mode) { - char errbuf[128]; - int err; + char errbuf[128]; + int err; + int i; - err = regcomp(&safe_abs_regex_c, safe_abs_regex, - REG_EXTENDED|REG_NOSUB); - if (err) { - regerror(err, &safe_abs_regex_c, errbuf, sizeof errbuf); - die("%s", errbuf); - } + if (use_real_mode) + sym_regex = sym_regex_realmode; + else + sym_regex = sym_regex_kernel; - err = regcomp(&safe_rel_regex_c, safe_rel_regex, - REG_EXTENDED|REG_NOSUB); - if (err) { - regerror(err, &safe_rel_regex_c, errbuf, sizeof errbuf); - die("%s", errbuf); - } + for (i = 0; i < S_NSYMTYPES; i++) { + if (!sym_regex[i]) + continue; + + err = regcomp(&sym_regex_c[i], sym_regex[i], + REG_EXTENDED|REG_NOSUB); + + if (err) { + regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); + die("%s", errbuf); + } + } +} + +static void die(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); } static const char *sym_type(unsigned type) @@ -153,13 +184,16 @@ static const char *rel_type(unsigned type) REL_TYPE(R_386_RELATIVE), REL_TYPE(R_386_GOTOFF), REL_TYPE(R_386_GOTPC), + REL_TYPE(R_386_8), + REL_TYPE(R_386_PC8), + REL_TYPE(R_386_16), + REL_TYPE(R_386_PC16), #undef REL_TYPE }; - const char *name = NULL; - if (type < ARRAY_SIZE(type_name)) + const char *name = "unknown type rel type name"; + if (type < ARRAY_SIZE(type_name) && type_name[type]) { name = type_name[type]; - if (!name) - name = "unknown"; + } return name; } @@ -189,7 +223,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) name = sym_strtab + sym->st_name; } else { - name = sec_name(secs[sym->st_shndx].shdr.sh_name); + name = sec_name(sym->st_shndx); } return name; } @@ -428,7 +462,7 @@ static void print_absolute_symbols(void) printf("\n"); } -static int print_absolute_relocs(FILE *f) +static void print_absolute_relocs(void) { int i, printed = 0; @@ -472,17 +506,18 @@ static int print_absolute_relocs(FILE *f) * Before warning check if this absolute symbol * relocation is harmless. */ - if (is_safe_abs_reloc(name) || - is_safe_rel_reloc(name)) + if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) continue; if (!printed) { - fprintf(f, "Unknown absolute relocations present\n"); - fprintf(f, "Offset Info Type Sym.Value Sym.Name\n"); + printf("WARNING: Absolute relocations" + " present\n"); + printf("Offset Info Type Sym.Value " + "Sym.Name\n"); printed = 1; } - fprintf(f, "%08x %08x %10s %08x %s\n", + printf("%08x %08x %10s %08x %s\n", rel->r_offset, rel->r_info, rel_type(ELF32_R_TYPE(rel->r_info)), @@ -492,12 +527,11 @@ static int print_absolute_relocs(FILE *f) } if (printed) - fputc('\n', f); - - return printed; + printf("\n"); } -static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) +static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), + int use_real_mode) { int i; /* Walk through the relocations */ @@ -522,31 +556,71 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) Elf32_Rel *rel; Elf32_Sym *sym; unsigned r_type; + const char *symname; + int shn_abs; + rel = &sec->reltab[j]; sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; r_type = ELF32_R_TYPE(rel->r_info); - /* Don't visit relocations to absolute symbols */ - if (sym->st_shndx == SHN_ABS && - !is_safe_rel_reloc(sym_name(sym_strtab, sym))) - continue; + + shn_abs = sym->st_shndx == SHN_ABS; switch (r_type) { case R_386_NONE: case R_386_PC32: + case R_386_PC16: + case R_386_PC8: case R_386_GOTPC: case R_386_GOTOFF: case R_386_GOT32: case R_386_PLT32: - /* Relative relocations don't need to - be adjusted */ + /* + * NONE can be ignored and and PC relative + * relocations don't need to be adjusted. + */ break; + + case R_386_16: + symname = sym_name(sym_strtab, sym); + if (!use_real_mode) + goto bad; + if (shn_abs) { + if (is_reloc(S_ABS, symname)) + break; + else if (!is_reloc(S_SEG, symname)) + goto bad; + } else { + if (is_reloc(S_LIN, symname)) + goto bad; + else + break; + } + visit(rel, sym); + break; + case R_386_32: - /* Visit relocations that need adjustment */ + symname = sym_name(sym_strtab, sym); + if (shn_abs) { + if (is_reloc(S_ABS, symname)) + break; + else if (!is_reloc(S_REL, symname)) + goto bad; + } else { + if (use_real_mode && + !is_reloc(S_LIN, symname)) + break; + } visit(rel, sym); break; default: die("Unsupported relocation type: %s (%d)\n", rel_type(r_type), r_type); + break; + bad: + symname = sym_name(sym_strtab, sym); + die("Invalid %s %s relocation: %s\n", + shn_abs ? "absolute" : "relative", + rel_type(r_type), symname); } } } @@ -554,8 +628,12 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) { - (void)rel; (void)sym; - reloc_count += 1; + (void)sym; + + if (ELF32_R_TYPE(rel->r_info) == R_386_16) + reloc16_count++; + else + reloc_count++; } static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) @@ -563,7 +641,10 @@ static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) (void)sym; /* Remember the address that needs to be adjusted. */ - relocs[reloc_idx++] = rel->r_offset; + if (ELF32_R_TYPE(rel->r_info) == R_386_16) + relocs16[reloc16_idx++] = rel->r_offset; + else + relocs[reloc_idx++] = rel->r_offset; } static int cmp_relocs(const void *va, const void *vb) @@ -573,23 +654,41 @@ static int cmp_relocs(const void *va, const void *vb) return (*a == *b)? 0 : (*a > *b)? 1 : -1; } -static void emit_relocs(int as_text) +static int write32(unsigned int v, FILE *f) +{ + unsigned char buf[4]; + + put_unaligned_le32(v, buf); + return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; +} + +static void emit_relocs(int as_text, int use_real_mode) { int i; /* Count how many relocations I have and allocate space for them. */ reloc_count = 0; - walk_relocs(count_reloc); + walk_relocs(count_reloc, use_real_mode); relocs = malloc(reloc_count * sizeof(relocs[0])); if (!relocs) { die("malloc of %d entries for relocs failed\n", reloc_count); } + + relocs16 = malloc(reloc16_count * sizeof(relocs[0])); + if (!relocs16) { + die("malloc of %d entries for relocs16 failed\n", + reloc16_count); + } /* Collect up the relocations */ reloc_idx = 0; - walk_relocs(collect_reloc); + walk_relocs(collect_reloc, use_real_mode); + + if (reloc16_count && !use_real_mode) + die("Segment relocations found but --realmode not specified\n"); /* Order the relocations for more efficient processing */ qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); + qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs); /* Print the relocations */ if (as_text) { @@ -598,61 +697,83 @@ static void emit_relocs(int as_text) */ printf(".section \".data.reloc\",\"a\"\n"); printf(".balign 4\n"); - for (i = 0; i < reloc_count; i++) { - printf("\t .long 0x%08lx\n", relocs[i]); + if (use_real_mode) { + printf("\t.long %lu\n", reloc16_count); + for (i = 0; i < reloc16_count; i++) + printf("\t.long 0x%08lx\n", relocs16[i]); + printf("\t.long %lu\n", reloc_count); + for (i = 0; i < reloc_count; i++) { + printf("\t.long 0x%08lx\n", relocs[i]); + } + } else { + for (i = 0; i < reloc_count; i++) { + printf("\t.long 0x%08lx\n", relocs[i]); + } + /* Print a stop */ + printf("\t.long 0x%08lx\n", (unsigned long)0); } + printf("\n"); } else { - unsigned char buf[4]; - /* Now print each relocation */ - for (i = 0; i < reloc_count; i++) { - buf[0] = (relocs[i] >> 0) & 0xff; - buf[1] = (relocs[i] >> 8) & 0xff; - buf[2] = (relocs[i] >> 16) & 0xff; - buf[3] = (relocs[i] >> 24) & 0xff; - fwrite(buf, 4, 1, stdout); + if (use_real_mode) { + write32(reloc16_count, stdout); + for (i = 0; i < reloc16_count; i++) + write32(relocs16[i], stdout); + write32(reloc_count, stdout); + + /* Now print each relocation */ + for (i = 0; i < reloc_count; i++) + write32(relocs[i], stdout); + } else { + /* Now print each relocation */ + for (i = 0; i < reloc_count; i++) { + write32(relocs[i], stdout); + } + + /* Print a stop */ + write32(0, stdout); } - /* Print a stop */ - memset(buf, 0, sizeof buf); - fwrite(buf, 4, 1, stdout); } } static void usage(void) { - die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); + die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); } int main(int argc, char **argv) { int show_absolute_syms, show_absolute_relocs; - int as_text; + int as_text, use_real_mode; const char *fname; FILE *fp; int i; - int err = 0; show_absolute_syms = 0; show_absolute_relocs = 0; as_text = 0; + use_real_mode = 0; fname = NULL; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (*arg == '-') { - if (strcmp(argv[1], "--abs-syms") == 0) { + if (strcmp(arg, "--abs-syms") == 0) { show_absolute_syms = 1; continue; } - - if (strcmp(argv[1], "--abs-relocs") == 0) { + if (strcmp(arg, "--abs-relocs") == 0) { show_absolute_relocs = 1; continue; } - else if (strcmp(argv[1], "--text") == 0) { + if (strcmp(arg, "--text") == 0) { as_text = 1; continue; } + if (strcmp(arg, "--realmode") == 0) { + use_real_mode = 1; + continue; + } } else if (!fname) { fname = arg; @@ -663,10 +784,7 @@ int main(int argc, char **argv) if (!fname) { usage(); } - - - regex_init(); - + regex_init(use_real_mode); fp = fopen(fname, "r"); if (!fp) { die("Cannot open %s: %s\n", @@ -682,10 +800,9 @@ int main(int argc, char **argv) return 0; } if (show_absolute_relocs) { - print_absolute_relocs(stdout); + print_absolute_relocs(); return 0; } - err = print_absolute_relocs(stderr); - emit_relocs(as_text); - return err; + emit_relocs(as_text, use_real_mode); + return 0; } |