Merge branch 'syslinux-3.7x'
authorH. Peter Anvin <hpa@zytor.com>
Mon, 27 Apr 2009 02:36:58 +0000 (19:36 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Mon, 27 Apr 2009 02:36:58 +0000 (19:36 -0700)
Conflicts:
version

108 files changed:
Makefile
com32/MCONFIG
com32/Makefile
com32/gdbstub/gdbstub.c
com32/gdbstub/serial.c
com32/gplinclude/cpuid.h
com32/gplinclude/vpd/vpd.h [new file with mode: 0644]
com32/gpllib/Makefile
com32/gpllib/dmi/dmi_base_board.c
com32/gpllib/dmi/dmi_battery.c
com32/gpllib/dmi/dmi_bios.c
com32/gpllib/dmi/dmi_ipmi.c
com32/gpllib/dmi/dmi_memory.c
com32/gpllib/dmi/dmi_processor.c
com32/gpllib/vpd/vpd.c [new file with mode: 0644]
com32/hdt/hdt-ata.c
com32/hdt/hdt-cli-cpu.c
com32/hdt/hdt-cli-dmi.c
com32/hdt/hdt-cli-hdt.c [new file with mode: 0644]
com32/hdt/hdt-cli-kernel.c
com32/hdt/hdt-cli-pci.c
com32/hdt/hdt-cli-pxe.c
com32/hdt/hdt-cli-syslinux.c
com32/hdt/hdt-cli-vesa.c
com32/hdt/hdt-cli-vpd.c [new file with mode: 0644]
com32/hdt/hdt-cli.c
com32/hdt/hdt-cli.h
com32/hdt/hdt-common.c
com32/hdt/hdt-common.h
com32/hdt/hdt-menu-dmi.c
com32/hdt/hdt-menu-processor.c
com32/hdt/hdt-menu-vpd.c [new file with mode: 0644]
com32/hdt/hdt-menu.c
com32/hdt/hdt-menu.h
com32/hdt/hdt.c
com32/hdt/hdt.h
com32/hdt/lib-ansi.c [new file with mode: 0644]
com32/hdt/lib-ansi.h [new file with mode: 0644]
com32/include/com32.h
com32/include/sys/cpu.h
com32/include/sys/pci.h
com32/include/syslinux/bootrm.h
com32/include/syslinux/keyboard.h
com32/include/syslinux/movebits.h
com32/lib/malloc.h
com32/lib/memcpy.S
com32/lib/memmove.S
com32/lib/mempcpy.S
com32/lib/memset.S
com32/lib/setjmp.S
com32/lib/sys/ansicon_write.c
com32/lib/syslinux/memmap.c
com32/lib/syslinux/memscan.c
com32/lib/syslinux/shuffle.c
com32/lib/syslinux/shuffle_pm.c
com32/lib/syslinux/shuffle_rm.c
com32/lib/syslinux/zonelist.c
com32/mboot/Makefile [new file with mode: 0644]
com32/mboot/apm.c [new file with mode: 0644]
com32/mboot/map.c [new file with mode: 0644]
com32/mboot/mb_header.h [moved from com32/modules/mb_header.h with 100% similarity]
com32/mboot/mb_info.h [moved from com32/modules/mb_info.h with 71% similarity]
com32/mboot/mboot.c [new file with mode: 0644]
com32/mboot/mboot.h [new file with mode: 0644]
com32/mboot/mem.c [new file with mode: 0644]
com32/menu/drain.c
com32/menu/execute.c
com32/modules/Makefile
com32/modules/chain.c
com32/modules/i386-elf.h [deleted file]
com32/modules/mboot.c [deleted file]
com32/modules/vpdtest.c [new file with mode: 0644]
com32/rosh/rosh.c
com32/samples/entrydump.c
core/adv.inc
core/bcopy32.inc
core/bcopyxx.inc [new file with mode: 0644]
core/bootsect.inc
core/cleanup.inc
core/cmdline.inc
core/com32.inc
core/comboot.inc
core/config.inc
core/conio.inc
core/cpuinit.inc
core/diskstart.inc [new file with mode: 0644]
core/dnsresolv.inc
core/extlinux.asm
core/font.inc
core/highmem.inc
core/isolinux.asm
core/keywords.inc
core/layout.inc
core/ldlinux.asm
core/macros.inc
core/parseconfig.inc
core/pxeidle.inc
core/pxelinux.asm
core/rawcon.inc
core/rllpack.inc
core/runkernel.inc
core/syslinux.ld
core/ui.inc
doc/comboot.txt
memdisk/setup.c
memdisk/start32.S
modules/pxechain.asm
version

index 4520c35..bdaffe6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -31,14 +31,16 @@ include $(topdir)/MCONFIG
 
 # List of module objects that should be installed for all derivatives
 MODULES = memdisk/memdisk memdump/memdump.com modules/*.com \
-       com32/menu/*.c32 com32/modules/*.c32 com32/hdt/*.c32 \
-       com32/rosh/*.c32
+       com32/menu/*.c32 com32/modules/*.c32 com32/mboot/*.c32 \
+       com32/hdt/*.c32 com32/rosh/*.c32
 
 # syslinux.exe is BTARGET so as to not require everyone to have the
 # mingw suite installed
 BTARGET  = version.gen version.h version.mk
 BOBJECTS = $(BTARGET) \
-       mbr/mbr.bin mbr/gptmbr.bin \
+       mbr/mbr.bin mbr/altmbr.bin mbr/gptmbr.bin \
+       mbr/mbr_c.bin mbr/altmbr_c.bin mbr/gptmbr_c.bin \
+       mbr/mbr_f.bin mbr/altmbr_f.bin mbr/gptmbr_f.bin \
        core/pxelinux.0 core/isolinux.bin core/isolinux-debug.bin \
        gpxe/gpxelinux.0 dos/syslinux.com win32/syslinux.exe \
        $(MODULES)
index 641111a..599cfb6 100644 (file)
@@ -35,8 +35,10 @@ endif
 CFLAGS     = $(GCCOPT) -W -Wall -march=i386 \
             -fomit-frame-pointer -D__COM32__ \
             -nostdinc -iwithprefix include \
-            -I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE)
-SFLAGS     = $(GCCOPT) -D__COM32__ -march=i386
+            -I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE) \
+            -Wp,-MT,$@,-MD,$(dir $@).$(notdir $@).d
+SFLAGS     = $(GCCOPT) -D__COM32__ -march=i386 \
+            -Wp,-MT,$@,-MD,$(dir $@).$(notdir $@).d
 LDFLAGS    = -m elf_i386 -T $(com32)/lib/com32.ld
 LIBGCC    := $(shell $(CC) $(GCCOPT) --print-libgcc)
 
index 64049d0..4a58485 100644 (file)
@@ -1,3 +1,3 @@
-SUBDIRS = lib gpllib libutil modules menu samples rosh cmenu hdt
+SUBDIRS = lib gpllib libutil modules mboot menu samples rosh cmenu hdt
 all tidy dist clean spotless install:
        set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
index 3e9ff5e..f235a34 100644 (file)
@@ -152,12 +152,12 @@ static void gdbmach_commit_hwbp ( struct hwbp *bp ) {
 
        /* Set/clear local enable bit */
        dr7 &= ~( 0x3 << 2 * regnum );
-       dr7 |= bp->enabled << 2 * regnum;
+       dr7 |= bp->enabled << 2 * regnum;
 }
 
 int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ) {
        struct hwbp *bp;
-       
+
        /* Check and convert breakpoint type to x86 type */
        switch ( type ) {
                case GDBMACH_WATCH:
index 1c4d4b6..2b9fc2e 100644 (file)
@@ -91,7 +91,7 @@ void serial_putc ( int ch ) {
        int status;
        for (;;) {
                status = uart_readb(UART_BASE + UART_LSR);
-               if (status & UART_LSR_THRE) { 
+               if (status & UART_LSR_THRE) {
                        /* TX buffer emtpy */
                        uart_writeb(ch, UART_BASE + UART_TBR);
                        break;
@@ -165,7 +165,7 @@ void serial_init ( void ) {
                goto out;
        }
        uart_writeb(lcs, UART_BASE + UART_LCR);
-       
+
        /* disable interrupts */
        uart_writeb(0x0, UART_BASE + UART_IER);
 
index 2473b41..ca1c314 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------- *
- *   
+ *
  *   Copyright 2006-2009 Erwan Velu - All Rights Reserved
  *
  *   Portions of this file taken from the Linux kernel,
diff --git a/com32/gplinclude/vpd/vpd.h b/com32/gplinclude/vpd/vpd.h
new file mode 100644 (file)
index 0000000..4bb1afc
--- /dev/null
@@ -0,0 +1,33 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2006 Erwan Velu - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef VPD_H
+#define VPD_H
+#include <inttypes.h>
+#include <stdbool.h>
+
+enum {VPD_TABLE_PRESENT = 100, ENOVPDTABLE};
+
+typedef struct {
+        char bios_build_id[10];
+        char box_serial_number[8];
+        char motherboard_serial_number[12];
+        char machine_type_model[8];
+        char bios_release_date[9];
+        char default_flash_filename[13];
+        char bios_version[255];
+        char base_address[6];
+        bool filled;
+} s_vpd;
+
+int vpd_decode(s_vpd *vpd);
+#endif
index 46ed42e..8e47d93 100644 (file)
@@ -10,7 +10,7 @@ REQFLAGS += -I../gplinclude
 
 LIBOBJS  = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o            \
            dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \
-          dmi/dmi_ipmi.o cpuid.o
+          dmi/dmi_ipmi.o cpuid.o vpd/vpd.o
 
 BINDIR   = /usr/bin
 LIBDIR   = /usr/lib
index f37feec..2f19fda 100644 (file)
@@ -35,4 +35,3 @@ const char *base_board_features_strings[]={
                 "Board is replaceable",
                 "Board is hot swappable" /* 4 */
 };
-
index 567254a..02b5e6d 100644 (file)
@@ -70,4 +70,3 @@ void dmi_battery_maximum_error(uint8_t code, char *error)
         else
                 sprintf(error,"%u%%", code);
 }
-
index 9458d49..1fea752 100644 (file)
@@ -77,4 +77,3 @@ const char *bios_charac_x2_strings[]={
     "Function key-initiated network boot is supported",
     "Targeted content distribution is supported" /* 2 */
 };
-
index 8ea5f79..8081375 100644 (file)
@@ -56,4 +56,3 @@ void dmi_ipmi_base_address(uint8_t type, const uint8_t *p, s_ipmi *ipmi)
                 ipmi->base_address = QWORD(p);
         }
 }
-
index dc354df..9067009 100644 (file)
@@ -169,4 +169,3 @@ void dmi_memory_device_speed(uint16_t code, char *speed)
  else
       sprintf(speed,"%u MHz", code);
 }
-
index f86f009..321f6e6 100644 (file)
@@ -430,4 +430,3 @@ const char *cpu_flags_strings[PROCESSOR_FLAGS_ELEMENTS]={
                 "IA64 (IA64 capabilities)", /* 30 */
                 "PBE (Pending break enabled)" /* 31 */
 };
-
diff --git a/com32/gpllib/vpd/vpd.c b/com32/gpllib/vpd/vpd.c
new file mode 100644 (file)
index 0000000..ff04b8b
--- /dev/null
@@ -0,0 +1,103 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2006 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "vpd/vpd.h"
+
+int vpd_checksum(char *buf, int len)
+{
+        uint8_t sum=0;
+        int a;
+
+        for(a=0; a<len; a++)
+                sum+=buf[a];
+        return (sum==0);
+}
+
+int vpd_decode(s_vpd *vpd) {
+  uint8_t buf[16];
+  char *p,*q;
+
+  /* Cleaning structures */
+  memset(&vpd->base_address,0,sizeof (vpd->base_address));
+  memset(&vpd->bios_build_id,0,sizeof (vpd->bios_build_id));
+  memset(&vpd->box_serial_number,0,sizeof (vpd->box_serial_number));
+  memset(&vpd->motherboard_serial_number,0,sizeof (vpd->motherboard_serial_number));
+  memset(&vpd->machine_type_model,0,sizeof (vpd->machine_type_model));
+  memset(&vpd->bios_release_date,0,sizeof (vpd->bios_release_date));
+  memset(&vpd->default_flash_filename,0,sizeof (vpd->default_flash_filename));
+  memset(&vpd->bios_version,0,sizeof (vpd->bios_version));
+
+  /* Until we found elements in the vpdtable, we consider them as not filled */
+  vpd->filled=false;
+
+  p=(char *)0xF0000; /* The start address to look at the dmi table */
+  for (q = p; q < p + 0x10000; q +=4) {
+        memcpy(buf, q, 5);
+        if(memcmp(buf, "\252\125VPD", 5)==0) {
+            snprintf(&vpd->base_address,5,"%X",q);
+             if (q[5] < 0x30)
+                 return -ENOVPDTABLE;
+
+            vpd->filled=true;
+             /* XSeries have longer records, exact length seems to vary. */
+             if (!(q[5] >= 0x45 && vpd_checksum(q, q[5]))
+               /* Some Netvista seem to work with this. */
+               && !(vpd_checksum(q, 0x30))
+               /* The Thinkpad/Thinkcentre checksum does *not* include the first 13 bytes. */
+               && !(vpd_checksum(q + 0x0D, 0x30 - 0x0D)))
+               {
+                /* A few systems have a bad checksum (xSeries 325, 330, 335
+                   and 345 with early BIOS) but the record is otherwise
+                   valid. */
+                        printf("VPD: Bad checksum!\n");
+               }
+
+             strncpy(vpd->bios_build_id,q+0x0D, 9);
+             strncpy(vpd->box_serial_number,q+0x16, 7);
+             strncpy(vpd->motherboard_serial_number,q+0x1D, 11);
+             strncpy(vpd->machine_type_model,q+0x28, 7);
+
+            if (q[5] < 0x44)
+                return VPD_TABLE_PRESENT;
+
+             strncpy(vpd->bios_release_date,q+0x30, 8);
+             strncpy(vpd->default_flash_filename,q+0x38, 12);
+
+            if (q[5] >= 0x46 && q[0x44] != 0x00) {
+                    strncpy(vpd->bios_version,q+0x44, 255);
+            }
+
+             return VPD_TABLE_PRESENT;
+         }
+  }
+  return -ENOVPDTABLE;
+}
+
+
index eb507d2..e0d6015 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <console.h>
+#include <getkey.h>
 
 #include "com32io.h"
+#include "hdt-common.h"
 #include "hdt-ata.h"
 
 #ifdef ATA
@@ -217,7 +219,7 @@ int get_disk_params(int disk, struct diskinfo *disk_info)
   memcpy(&dp, __com32.cs_bounce, sizeof(struct device_parameter));
 
   if (outreg.eflags.l & EFLAGS_CF) {
-    printf("Disk 0x%X doesn't supports EDD 3.0\n", disk);
+    more_printf("Disk 0x%X doesn't supports EDD 3.0\n", disk);
     return -1;
   }
 
@@ -260,7 +262,7 @@ int get_disk_params(int disk, struct diskinfo *disk_info)
   memcpy(&aid, __com32.cs_bounce, sizeof(struct ata_identify_device));
 
   if (outreg.eflags.l & EFLAGS_CF) {
-    printf("Disk 0x%X: Failed to Identify Device\n", disk);
+    more_printf("Disk 0x%X: Failed to Identify Device\n", disk);
     //FIXME
     return 0;
   }
@@ -270,8 +272,8 @@ int get_disk_params(int disk, struct diskinfo *disk_info)
   char buff[sizeof(struct ata_identify_device)];
   memcpy(buff, &aid, sizeof(struct ata_identify_device));
   for (int j = 0; j < sizeof(struct ata_identify_device); j++)
-    printf("model=|%c|\n", buff[j]);
-  printf("Disk 0x%X : %s %s %s\n", disk, aid.model, aid.fw_rev,
+    more_printf("model=|%c|\n", buff[j]);
+  more_printf("Disk 0x%X : %s %s %s\n", disk, aid.model, aid.fw_rev,
          aid.serial_no);
 #endif
 
index cfd66ef..f0f0a1b 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
-void show_cpu(struct s_hardware *hardware)
+void main_show_cpu(int argc __unused, char **argv __unused,
+                  struct s_hardware *hardware)
 {
-  char buffer[81];
-  char buffer1[81];
-  clear_screen();
-  more_printf("CPU\n");
-  more_printf("Vendor    : %s\n", hardware->cpu.vendor);
-  more_printf("Model     : %s\n", hardware->cpu.model);
-  more_printf("Vendor ID : %d\n", hardware->cpu.vendor_id);
-  more_printf("Family ID : %d\n", hardware->cpu.family);
-  more_printf("Model  ID : %d\n", hardware->cpu.model_id);
-  more_printf("Stepping  : %d\n", hardware->cpu.stepping);
-  more_printf("FSB       : %d MHz\n",
-        hardware->dmi.processor.external_clock);
-  more_printf("Cur. Speed: %d MHz\n",
-        hardware->dmi.processor.current_speed);
-  more_printf("Max Speed : %d MHz\n", hardware->dmi.processor.max_speed);
-  more_printf("Upgrade   : %s\n", hardware->dmi.processor.upgrade);
-  if (hardware->cpu.flags.smp) {
-    more_printf("SMP       : yes\n");
-  } else {
-    more_printf("SMP       : no\n");
-  }
-  if (hardware->cpu.flags.lm) {
-    more_printf("x86_64    : yes\n");
-  } else {
-    more_printf("x86_64    : no\n");
-  }
-
-  memset(buffer, 0, sizeof(buffer));
-  memset(buffer1, 0, sizeof(buffer1));
-  if (hardware->cpu.flags.fpu)
-    strcat(buffer1, "fpu ");
-  if (hardware->cpu.flags.vme)
-    strcat(buffer1, "vme ");
-  if (hardware->cpu.flags.de)
-    strcat(buffer1, "de ");
-  if (hardware->cpu.flags.pse)
-    strcat(buffer1, "pse ");
-  if (hardware->cpu.flags.tsc)
-    strcat(buffer1, "tsc ");
-  if (hardware->cpu.flags.msr)
-    strcat(buffer1, "msr ");
-  if (hardware->cpu.flags.pae)
-    strcat(buffer1, "pae ");
-  if (hardware->cpu.flags.mce)
-    strcat(buffer1, "mce ");
-  if (hardware->cpu.flags.cx8)
-    strcat(buffer1, "cx8 ");
-  if (hardware->cpu.flags.apic)
-    strcat(buffer1, "apic ");
-  if (hardware->cpu.flags.sep)
-    strcat(buffer1, "sep ");
-  if (hardware->cpu.flags.mtrr)
-    strcat(buffer1, "mtrr ");
-  if (hardware->cpu.flags.pge)
-    strcat(buffer1, "pge ");
-  if (hardware->cpu.flags.mca)
-    strcat(buffer1, "mca ");
-  snprintf(buffer, sizeof buffer, "Flags     : %s\n", buffer1);
-  more_printf(buffer);
-
-  memset(buffer, 0, sizeof(buffer));
-  memset(buffer1, 0, sizeof(buffer1));
-  if (hardware->cpu.flags.cmov)
-    strcat(buffer1, "cmov ");
-  if (hardware->cpu.flags.pat)
-    strcat(buffer1, "pat ");
-  if (hardware->cpu.flags.pse_36)
-    strcat(buffer1, "pse_36 ");
-  if (hardware->cpu.flags.psn)
-    strcat(buffer1, "psn ");
-  if (hardware->cpu.flags.clflsh)
-    strcat(buffer1, "clflsh ");
-  if (hardware->cpu.flags.dts)
-    strcat(buffer1, "dts ");
-  if (hardware->cpu.flags.acpi)
-    strcat(buffer1, "acpi ");
-  if (hardware->cpu.flags.mmx)
-    strcat(buffer1, "mmx ");
-  if (hardware->cpu.flags.sse)
-    strcat(buffer1, "sse ");
-  if (hardware->cpu.flags.sse2)
-    strcat(buffer1, "sse2 ");
-  if (hardware->cpu.flags.ss)
-    strcat(buffer1, "ss ");
-  snprintf(buffer, sizeof buffer, "Flags     : %s\n", buffer1);
-  more_printf(buffer);
-
-  memset(buffer, 0, sizeof(buffer));
-  memset(buffer1, 0, sizeof(buffer1));
-  if (hardware->cpu.flags.htt)
-    strcat(buffer1, "ht ");
-  if (hardware->cpu.flags.acc)
-    strcat(buffer1, "acc ");
-  if (hardware->cpu.flags.syscall)
-    strcat(buffer1, "syscall ");
-  if (hardware->cpu.flags.mp)
-    strcat(buffer1, "mp ");
-  if (hardware->cpu.flags.nx)
-    strcat(buffer1, "nx ");
-  if (hardware->cpu.flags.mmxext)
-    strcat(buffer1, "mmxext ");
-  if (hardware->cpu.flags.lm)
-    strcat(buffer1, "lm ");
-  if (hardware->cpu.flags.nowext)
-    strcat(buffer1, "3dnowext ");
-  if (hardware->cpu.flags.now)
-    strcat(buffer1, "3dnow! ");
-  snprintf(buffer, sizeof buffer, "Flags     : %s\n", buffer1);
-  more_printf(buffer);
+       cpu_detect(hardware);
+       detect_dmi(hardware);
+       more_printf("CPU\n");
+       more_printf(" Manufacturer : %s \n", hardware->cpu.vendor);
+       more_printf(" Product      : %s \n", del_multi_spaces(hardware->cpu.model));
+       if ((hardware->cpu.flags.lm == false)
+           && (hardware->cpu.flags.smp == false)) {
+               more_printf(" Features     : %d MhZ : x86 32bits\n",
+                           hardware->dmi.processor.current_speed);
+       } else if ((hardware->cpu.flags.lm == false)
+                  && (hardware->cpu.flags.smp == true)) {
+               more_printf(" Features     : %d MhZ : x86 32bits SMP\n",
+                           hardware->dmi.processor.current_speed);
+       } else if ((hardware->cpu.flags.lm == true)
+                  && (hardware->cpu.flags.smp == false)) {
+               more_printf(" Features     : %d MhZ : x86_64 64bits\n",
+                           hardware->dmi.processor.current_speed);
+       } else {
+               more_printf(" Features     : %d MhZ : x86_64 64bits SMP\n",
+                           hardware->dmi.processor.current_speed);
+       }
 }
 
-static void show_cpu_help()
+static void show_cpu(int argc __unused, char **argv __unused,
+                    struct s_hardware *hardware)
 {
-  more_printf("Show supports the following commands : %s\n", CLI_CPU);
-}
+       char buffer[81];
+       char buffer1[81];
+       reset_more_printf();
+       more_printf("CPU\n");
+       more_printf("Vendor    : %s\n", hardware->cpu.vendor);
+       more_printf("Model     : %s\n", hardware->cpu.model);
+       more_printf("Vendor ID : %d\n", hardware->cpu.vendor_id);
+       more_printf("Family ID : %d\n", hardware->cpu.family);
+       more_printf("Model  ID : %d\n", hardware->cpu.model_id);
+       more_printf("Stepping  : %d\n", hardware->cpu.stepping);
+       more_printf("FSB       : %d MHz\n",
+                   hardware->dmi.processor.external_clock);
+       more_printf("Cur. Speed: %d MHz\n",
+                   hardware->dmi.processor.current_speed);
+       more_printf("Max Speed : %d MHz\n", hardware->dmi.processor.max_speed);
+       more_printf("Upgrade   : %s\n", hardware->dmi.processor.upgrade);
+       if (hardware->cpu.flags.smp) {
+               more_printf("SMP       : yes\n");
+       } else {
+               more_printf("SMP       : no\n");
+       }
+       if (hardware->cpu.flags.lm) {
+               more_printf("x86_64    : yes\n");
+       } else {
+               more_printf("x86_64    : no\n");
+       }
 
-static void cpu_show(char *item, struct s_hardware *hardware)
-{
-  if (!strncmp(item, CLI_CPU, sizeof(CLI_CPU) - 1)) {
-    show_cpu(hardware);
-    return;
-  }
-  show_cpu_help();
-}
+       memset(buffer, 0, sizeof(buffer));
+       memset(buffer1, 0, sizeof(buffer1));
+       if (hardware->cpu.flags.fpu)
+               strcat(buffer1, "fpu ");
+       if (hardware->cpu.flags.vme)
+               strcat(buffer1, "vme ");
+       if (hardware->cpu.flags.de)
+               strcat(buffer1, "de ");
+       if (hardware->cpu.flags.pse)
+               strcat(buffer1, "pse ");
+       if (hardware->cpu.flags.tsc)
+               strcat(buffer1, "tsc ");
+       if (hardware->cpu.flags.msr)
+               strcat(buffer1, "msr ");
+       if (hardware->cpu.flags.pae)
+               strcat(buffer1, "pae ");
+       if (hardware->cpu.flags.mce)
+               strcat(buffer1, "mce ");
+       if (hardware->cpu.flags.cx8)
+               strcat(buffer1, "cx8 ");
+       if (hardware->cpu.flags.apic)
+               strcat(buffer1, "apic ");
+       if (hardware->cpu.flags.sep)
+               strcat(buffer1, "sep ");
+       if (hardware->cpu.flags.mtrr)
+               strcat(buffer1, "mtrr ");
+       if (hardware->cpu.flags.pge)
+               strcat(buffer1, "pge ");
+       if (hardware->cpu.flags.mca)
+               strcat(buffer1, "mca ");
+       if (buffer1[0]) {
+               snprintf(buffer, sizeof buffer, "Flags     : %s\n", buffer1);
+               more_printf(buffer);
+       }
 
-void handle_cpu_commands(char *cli_line, struct s_hardware *hardware)
-{
-  if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-    cpu_show(strstr(cli_line, "show") + sizeof(CLI_SHOW), hardware);
-    return;
-  }
-}
+       memset(buffer, 0, sizeof(buffer));
+       memset(buffer1, 0, sizeof(buffer1));
+       if (hardware->cpu.flags.cmov)
+               strcat(buffer1, "cmov ");
+       if (hardware->cpu.flags.pat)
+               strcat(buffer1, "pat ");
+       if (hardware->cpu.flags.pse_36)
+               strcat(buffer1, "pse_36 ");
+       if (hardware->cpu.flags.psn)
+               strcat(buffer1, "psn ");
+       if (hardware->cpu.flags.clflsh)
+               strcat(buffer1, "clflsh ");
+       if (hardware->cpu.flags.dts)
+               strcat(buffer1, "dts ");
+       if (hardware->cpu.flags.acpi)
+               strcat(buffer1, "acpi ");
+       if (hardware->cpu.flags.mmx)
+               strcat(buffer1, "mmx ");
+       if (hardware->cpu.flags.sse)
+               strcat(buffer1, "sse ");
+       if (hardware->cpu.flags.sse2)
+               strcat(buffer1, "sse2 ");
+       if (hardware->cpu.flags.ss)
+               strcat(buffer1, "ss ");
+       if (buffer1[0]) {
+               snprintf(buffer, sizeof buffer, "Flags     : %s\n", buffer1);
+               more_printf(buffer);
+       }
 
-void main_show_cpu(struct s_hardware *hardware)
-{
-  cpu_detect(hardware);
-  detect_dmi(hardware);
-  more_printf("CPU\n");
-  more_printf(" Manufacturer :  %s \n", hardware->cpu.vendor);
-  more_printf(" Product      :  %s \n", hardware->cpu.model);
-  if ((hardware->cpu.flags.lm == false)
-      && (hardware->cpu.flags.smp == false)) {
-    more_printf(" Features     :  %d MhZ : x86 32bits\n",
-          hardware->dmi.processor.current_speed);
-  } else if ((hardware->cpu.flags.lm == false)
-       && (hardware->cpu.flags.smp == true)) {
-    more_printf(" Features     :  %d MhZ : x86 32bits SMP\n",
-          hardware->dmi.processor.current_speed);
-  } else if ((hardware->cpu.flags.lm == true)
-       && (hardware->cpu.flags.smp == false)) {
-    more_printf(" Features     :  %d MhZ : x86_64 64bits\n",
-          hardware->dmi.processor.current_speed);
-  } else {
-    more_printf(" Features     :  %d MhZ : x86_64 64bits SMP\n",
-          hardware->dmi.processor.current_speed);
-  }
+       memset(buffer, 0, sizeof(buffer));
+       memset(buffer1, 0, sizeof(buffer1));
+       if (hardware->cpu.flags.htt)
+               strcat(buffer1, "ht ");
+       if (hardware->cpu.flags.acc)
+               strcat(buffer1, "acc ");
+       if (hardware->cpu.flags.syscall)
+               strcat(buffer1, "syscall ");
+       if (hardware->cpu.flags.mp)
+               strcat(buffer1, "mp ");
+       if (hardware->cpu.flags.nx)
+               strcat(buffer1, "nx ");
+       if (hardware->cpu.flags.mmxext)
+               strcat(buffer1, "mmxext ");
+       if (hardware->cpu.flags.lm)
+               strcat(buffer1, "lm ");
+       if (hardware->cpu.flags.nowext)
+               strcat(buffer1, "3dnowext ");
+       if (hardware->cpu.flags.now)
+               strcat(buffer1, "3dnow! ");
+       if (buffer1[0]) {
+               snprintf(buffer, sizeof buffer, "Flags     : %s\n", buffer1);
+               more_printf(buffer);
+       }
 }
+
+struct cli_module_descr cpu_show_modules = {
+       .modules = NULL,
+       .default_callback = show_cpu,
+};
+
+struct cli_mode_descr cpu_mode = {
+       .mode = CPU_MODE,
+       .name = CLI_CPU,
+       .default_modules = NULL,
+       .show_modules = &cpu_show_modules,
+       .set_modules = NULL,
+};
index a7ea872..d395c67 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
-static void show_dmi_modules(int argc, char** argv,
+static void show_dmi_modules(int argc __unused, char** argv __unused,
                              struct s_hardware *hardware)
 {
   char available_dmi_commands[1024];
   memset(available_dmi_commands, 0, sizeof(available_dmi_commands));
 
-  if (hardware->dmi.base_board.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_BASE_BOARD,
-      sizeof(CLI_DMI_BASE_BOARD) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-  if (hardware->dmi.battery.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_BATTERY,
-      sizeof(CLI_DMI_BATTERY) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-  if (hardware->dmi.bios.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_BIOS,
-      sizeof(CLI_DMI_BIOS) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-  if (hardware->dmi.chassis.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_CHASSIS,
-      sizeof(CLI_DMI_CHASSIS) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-  for (int i = 0; i < hardware->dmi.memory_count; i++) {
-    if (hardware->dmi.memory[i].filled == true) {
-      strncat(available_dmi_commands, CLI_DMI_MEMORY,
-        sizeof(CLI_DMI_MEMORY) - 1);
-      strncat(available_dmi_commands, " bank<bank_number> ",
-        19);
-      break;
-    }
-  }
-  if (hardware->dmi.processor.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_PROCESSOR,
-      sizeof(CLI_DMI_PROCESSOR) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-  if (hardware->dmi.system.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_SYSTEM,
-      sizeof(CLI_DMI_SYSTEM) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-  if (hardware->dmi.ipmi.filled == true) {
-    strncat(available_dmi_commands, CLI_DMI_IPMI,
-      sizeof(CLI_DMI_IPMI) - 1);
-    strncat(available_dmi_commands, " ", 1);
-  }
-
-  printf("Available DMI modules: %s\n", available_dmi_commands);
-}
-
-static void show_dmi_help(int argc, char** argv,
-                          struct s_hardware *hardware)
-{
-  more_printf("Show supports the following commands : \n");
-  more_printf(" %s\n", CLI_SHOW_LIST);
-  more_printf(" <module_name>\n");
-  more_printf(" -\n");
-  show_dmi_modules(0, NULL, hardware);
+  printf("Available DMI modules on your system:\n");
+       if (hardware->dmi.base_board.filled == true)
+               printf("\t%s\n", CLI_DMI_BASE_BOARD);
+       if (hardware->dmi.battery.filled == true)
+               printf("\t%s\n", CLI_DMI_BATTERY);
+       if (hardware->dmi.bios.filled == true)
+               printf("\t%s\n", CLI_DMI_BIOS);
+       if (hardware->dmi.chassis.filled == true)
+               printf("\t%s\n", CLI_DMI_CHASSIS);
+       for (int i = 0; i < hardware->dmi.memory_count; i++) {
+               if (hardware->dmi.memory[i].filled == true) {
+                       printf("\tbank <number>\n");
+                       break;
+               }
+       }
+       if (hardware->dmi.processor.filled == true)
+               printf("\t%s\n", CLI_DMI_PROCESSOR);
+       if (hardware->dmi.system.filled == true)
+               printf("\t%s\n", CLI_DMI_SYSTEM);
+       if (hardware->dmi.ipmi.filled == true)
+               printf("\t%s\n", CLI_DMI_IPMI);
 }
 
-static void show_dmi_base_board(int argc, char** argv,
+static void show_dmi_base_board(int argc __unused, char** argv __unused,
                                 struct s_hardware *hardware)
 {
   if (hardware->dmi.base_board.filled == false) {
-    printf("Base_board module not available\n");
+    printf("base_board information not found on your system, see "
+          "`show list' to see which module is available.\n");
     return;
   }
-  clear_screen();
+  reset_more_printf();
   more_printf("Base board\n");
   more_printf(" Manufacturer : %s\n",
         hardware->dmi.base_board.manufacturer);
@@ -123,33 +89,34 @@ static void show_dmi_base_board(int argc, char** argv,
   }
 }
 
-static void show_dmi_system(int argc, char** argv,
+static void show_dmi_system(int argc __unused, char** argv __unused,
                             struct s_hardware *hardware)
 {
   if (hardware->dmi.system.filled == false) {
-    printf("System module not available\n");
+    printf("system information not found on your system, see "
+          "`show list' to see which module is available.\n");
     return;
   }
-  clear_screen();
-  more_printf("System\n");
-  more_printf(" Manufacturer : %s\n", hardware->dmi.system.manufacturer);
-  more_printf(" Product Name : %s\n", hardware->dmi.system.product_name);
-  more_printf(" Version      : %s\n", hardware->dmi.system.version);
-  more_printf(" Serial       : %s\n", hardware->dmi.system.serial);
-  more_printf(" UUID         : %s\n", hardware->dmi.system.uuid);
-  more_printf(" Wakeup Type  : %s\n", hardware->dmi.system.wakeup_type);
-  more_printf(" SKU Number   : %s\n", hardware->dmi.system.sku_number);
-  more_printf(" Family       : %s\n", hardware->dmi.system.family);
+  printf("System\n");
+  printf(" Manufacturer : %s\n", hardware->dmi.system.manufacturer);
+  printf(" Product Name : %s\n", hardware->dmi.system.product_name);
+  printf(" Version      : %s\n", hardware->dmi.system.version);
+  printf(" Serial       : %s\n", hardware->dmi.system.serial);
+  printf(" UUID         : %s\n", hardware->dmi.system.uuid);
+  printf(" Wakeup Type  : %s\n", hardware->dmi.system.wakeup_type);
+  printf(" SKU Number   : %s\n", hardware->dmi.system.sku_number);
+  printf(" Family       : %s\n", hardware->dmi.system.family);
 }
 
-static void show_dmi_bios(int argc, char** argv,
+static void show_dmi_bios(int argc __unused, char** argv __unused,
                           struct s_hardware *hardware)
 {
   if (hardware->dmi.bios.filled == false) {
-    printf("Bios module not available\n");
+    printf("bios information not found on your system, see "
+          "`show list' to see which module is available.\n");
     return;
   }
-  clear_screen();
+  reset_more_printf();
   more_printf("BIOS\n");
   more_printf(" Vendor            : %s\n", hardware->dmi.bios.vendor);
   more_printf(" Version           : %s\n", hardware->dmi.bios.version);
@@ -188,105 +155,105 @@ static void show_dmi_bios(int argc, char** argv,
 
 }
 
-static void show_dmi_chassis(int argc, char** argv,
+static void show_dmi_chassis(int argc __unused, char** argv __unused,
                              struct s_hardware *hardware)
 {
   if (hardware->dmi.chassis.filled == false) {
-    printf("Chassis module not available\n");
+    more_printf("chassis information not found on your system, see "
+          "`show list' to see which module is available.\n");
     return;
   }
-  clear_screen();
-  more_printf("Chassis\n");
-  more_printf(" Manufacturer       : %s\n",
+  printf("Chassis\n");
+  printf(" Manufacturer       : %s\n",
         hardware->dmi.chassis.manufacturer);
-  more_printf(" Type               : %s\n", hardware->dmi.chassis.type);
-  more_printf(" Lock               : %s\n", hardware->dmi.chassis.lock);
-  more_printf(" Version            : %s\n",
+  printf(" Type               : %s\n", hardware->dmi.chassis.type);
+  printf(" Lock               : %s\n", hardware->dmi.chassis.lock);
+  printf(" Version            : %s\n",
         hardware->dmi.chassis.version);
-  more_printf(" Serial             : %s\n", hardware->dmi.chassis.serial);
-  more_printf(" Asset Tag          : %s\n",
-        hardware->dmi.chassis.asset_tag);
-  more_printf(" Boot up state      : %s\n",
+  printf(" Serial             : %s\n", hardware->dmi.chassis.serial);
+  printf(" Asset Tag          : %s\n",
+        del_multi_spaces(hardware->dmi.chassis.asset_tag));
+  printf(" Boot up state      : %s\n",
         hardware->dmi.chassis.boot_up_state);
-  more_printf(" Power supply state : %s\n",
+  printf(" Power supply state : %s\n",
         hardware->dmi.chassis.power_supply_state);
-  more_printf(" Thermal state      : %s\n",
+  printf(" Thermal state      : %s\n",
         hardware->dmi.chassis.thermal_state);
-  more_printf(" Security Status    : %s\n",
+  printf(" Security Status    : %s\n",
         hardware->dmi.chassis.security_status);
-  more_printf(" OEM Information    : %s\n",
+  printf(" OEM Information    : %s\n",
         hardware->dmi.chassis.oem_information);
-  more_printf(" Height             : %u\n", hardware->dmi.chassis.height);
-  more_printf(" NB Power Cords     : %u\n",
+  printf(" Height             : %u\n", hardware->dmi.chassis.height);
+  printf(" NB Power Cords     : %u\n",
         hardware->dmi.chassis.nb_power_cords);
 }
 
-static void show_dmi_ipmi(int argc, char** argv,
+static void show_dmi_ipmi(int argc __unused, char **argv __unused,
                              struct s_hardware *hardware)
 {
   if (hardware->dmi.ipmi.filled == false) {
-    printf("IPMI module not available\n");
+    more_printf("IPMI module not available\n");
     return;
   }
-  clear_screen();
-  more_printf("IPMI\n");
-  more_printf(" Interface Type     : %s\n",
+  printf("IPMI\n");
+  printf(" Interface Type     : %s\n",
         hardware->dmi.ipmi.interface_type);
-  more_printf(" Specification Ver. : %u.%u\n",
+  printf(" Specification Ver. : %u.%u\n",
        hardware->dmi.ipmi.major_specification_version,
        hardware->dmi.ipmi.minor_specification_version);
-  more_printf(" I2C Slave Address  : 0x%02x\n",
+  printf(" I2C Slave Address  : 0x%02x\n",
        hardware->dmi.ipmi.I2C_slave_address);
-  more_printf(" Nv Storage Address : %u\n",
+  printf(" Nv Storage Address : %u\n",
         hardware->dmi.ipmi.nv_address);
   uint32_t high = hardware->dmi.ipmi.base_address >> 32;
   uint32_t low  = hardware->dmi.ipmi.base_address & 0xFFFF;
-  more_printf(" Base Address       : %08X%08X\n",
+  printf(" Base Address       : %08X%08X\n",
        high,(low & ~1));
-  more_printf(" IRQ                : %d\n",
+  printf(" IRQ                : %d\n",
         hardware->dmi.ipmi.irq);
 }
 
-static void show_dmi_battery(int argc, char** argv,
+static void show_dmi_battery(int argc __unused, char** argv __unused,
                              struct s_hardware *hardware)
 {
   if (hardware->dmi.battery.filled == false) {
-    printf("Battery module not available\n");
+    printf("battery information not found on your system, see "
+          "`show list' to see which module is available.\n");
     return;
   }
-  clear_screen();
-  more_printf("Battery \n");
-  more_printf(" Vendor             : %s\n",
+  printf("Battery \n");
+  printf(" Vendor             : %s\n",
         hardware->dmi.battery.manufacturer);
-  more_printf(" Manufacture Date   : %s\n",
+  printf(" Manufacture Date   : %s\n",
         hardware->dmi.battery.manufacture_date);
-  more_printf(" Serial             : %s\n", hardware->dmi.battery.serial);
-  more_printf(" Name               : %s\n", hardware->dmi.battery.name);
-  more_printf(" Chemistry          : %s\n",
+  printf(" Serial             : %s\n", hardware->dmi.battery.serial);
+  printf(" Name               : %s\n", hardware->dmi.battery.name);
+  printf(" Chemistry          : %s\n",
         hardware->dmi.battery.chemistry);
-  more_printf(" Design Capacity    : %s\n",
+  printf(" Design Capacity    : %s\n",
         hardware->dmi.battery.design_capacity);
-  more_printf(" Design Voltage     : %s\n",
+  printf(" Design Voltage     : %s\n",
         hardware->dmi.battery.design_voltage);
-  more_printf(" SBDS               : %s\n", hardware->dmi.battery.sbds);
-  more_printf(" SBDS Manuf. Date   : %s\n",
+  printf(" SBDS               : %s\n", hardware->dmi.battery.sbds);
+  printf(" SBDS Manuf. Date   : %s\n",
         hardware->dmi.battery.sbds_manufacture_date);
-  more_printf(" SBDS Chemistry     : %s\n",
+  printf(" SBDS Chemistry     : %s\n",
         hardware->dmi.battery.sbds_chemistry);
-  more_printf(" Maximum Error      : %s\n",
+  printf(" Maximum Error      : %s\n",
         hardware->dmi.battery.maximum_error);
-  more_printf(" OEM Info           : %s\n",
+  printf(" OEM Info           : %s\n",
         hardware->dmi.battery.oem_info);
 }
 
-static void show_dmi_cpu(int argc, char** argv,
+static void show_dmi_cpu(int argc __unused, char** argv __unused,
                          struct s_hardware *hardware)
 {
   if (hardware->dmi.processor.filled == false) {
-    printf("Processor module not available\n");
+    printf("processor information not found on your system, see "
+          "`show list' to see which module is available.\n");
     return;
   }
-  clear_screen();
+  reset_more_printf();
   more_printf("CPU\n");
   more_printf(" Socket Designation : %s\n",
         hardware->dmi.processor.socket_designation);
@@ -339,7 +306,7 @@ static void show_dmi_cpu(int argc, char** argv,
 static void show_dmi_memory_bank(int argc, char** argv,
                                  struct s_hardware *hardware)
 {
-  long bank = -1;
+  int bank = -1;
 
   /* Sanitize arguments */
   if (argc > 0)
@@ -360,34 +327,35 @@ static void show_dmi_memory_bank(int argc, char** argv,
   }
 
   printf("Memory Bank %d\n", bank);
-  more_printf(" Form Factor  : %s\n",
+  printf(" Form Factor  : %s\n",
         hardware->dmi.memory[bank].form_factor);
-  more_printf(" Type         : %s\n", hardware->dmi.memory[bank].type);
-  more_printf(" Type Detail  : %s\n",
+  printf(" Type         : %s\n", hardware->dmi.memory[bank].type);
+  printf(" Type Detail  : %s\n",
         hardware->dmi.memory[bank].type_detail);
-  more_printf(" Speed        : %s\n", hardware->dmi.memory[bank].speed);
-  more_printf(" Size         : %s\n", hardware->dmi.memory[bank].size);
-  more_printf(" Device Set   : %s\n",
+  printf(" Speed        : %s\n", hardware->dmi.memory[bank].speed);
+  printf(" Size         : %s\n", hardware->dmi.memory[bank].size);
+  printf(" Device Set   : %s\n",
         hardware->dmi.memory[bank].device_set);
-  more_printf(" Device Loc.  : %s\n",
+  printf(" Device Loc.  : %s\n",
         hardware->dmi.memory[bank].device_locator);
-  more_printf(" Bank Locator : %s\n",
+  printf(" Bank Locator : %s\n",
         hardware->dmi.memory[bank].bank_locator);
-  more_printf(" Total Width  : %s\n",
+  printf(" Total Width  : %s\n",
         hardware->dmi.memory[bank].total_width);
-  more_printf(" Data Width   : %s\n",
+  printf(" Data Width   : %s\n",
         hardware->dmi.memory[bank].data_width);
-  more_printf(" Error        : %s\n", hardware->dmi.memory[bank].error);
-  more_printf(" Vendor       : %s\n",
+  printf(" Error        : %s\n", hardware->dmi.memory[bank].error);
+  printf(" Vendor       : %s\n",
         hardware->dmi.memory[bank].manufacturer);
-  more_printf(" Serial       : %s\n", hardware->dmi.memory[bank].serial);
-  more_printf(" Asset Tag    : %s\n",
+  printf(" Serial       : %s\n", hardware->dmi.memory[bank].serial);
+  printf(" Asset Tag    : %s\n",
         hardware->dmi.memory[bank].asset_tag);
-  more_printf(" Part Number  : %s\n",
+  printf(" Part Number  : %s\n",
         hardware->dmi.memory[bank].part_number);
 }
 
-void main_show_dmi(struct s_hardware *hardware)
+void main_show_dmi(int argc __unused, char **argv __unused,
+                  struct s_hardware *hardware)
 {
 
   detect_dmi(hardware);
@@ -403,7 +371,7 @@ void main_show_dmi(struct s_hardware *hardware)
   show_dmi_modules(0, NULL, hardware);
 }
 
-void show_dmi_memory_modules(int argc, char** argv,
+void show_dmi_memory_modules(int argc __unused, char** argv __unused,
                              struct s_hardware *hardware)
 {
   int clear = 1, show_free_banks = 1;
@@ -426,7 +394,7 @@ void show_dmi_memory_modules(int argc, char** argv,
   memset(available_dmi_commands, 0, sizeof(available_dmi_commands));
 
   if (hardware->dmi.memory_count <= 0) {
-    printf("No memory module found\n");
+    more_printf("No memory module found\n");
     return;
   }
 
@@ -445,12 +413,12 @@ void show_dmi_memory_modules(int argc, char** argv,
       if (show_free_banks == false) {
         if (strncmp
             (hardware->dmi.memory[i].size, "Free", 4))
-          printf(" bank %02d      : %s %s@%s\n",
+          more_printf(" bank %02d      : %s %s@%s\n",
                  i, hardware->dmi.memory[i].size,
                  hardware->dmi.memory[i].type,
                  hardware->dmi.memory[i].speed);
       } else {
-        printf(" bank %02d      : %s %s@%s\n", i,
+        more_printf(" bank %02d      : %s %s@%s\n", i,
                hardware->dmi.memory[i].size,
                hardware->dmi.memory[i].type,
                hardware->dmi.memory[i].speed);
@@ -462,11 +430,11 @@ void show_dmi_memory_modules(int argc, char** argv,
   //printf("Type 'show bank<bank_number>' for more details.\n");
 
 usage:
-  printf("show memory <clear screen? <show free banks?>>\n");
+  more_printf("show memory <clear screen? <show free banks?>>\n");
   return;
 }
 
-struct commands_module list_dmi_show_modules[] = {
+struct cli_callback_descr list_dmi_show_modules[] = {
   {
     .name = CLI_DMI_BASE_BOARD,
     .exec = show_dmi_base_board,
@@ -507,14 +475,21 @@ struct commands_module list_dmi_show_modules[] = {
     .name = CLI_DMI_LIST,
     .exec = show_dmi_modules,
   },
+  {
+    .name = NULL,
+    .exec = NULL,
+  },
 };
 
-struct commands_module_descr dmi_show_modules = {
-  .modules = list_dmi_show_modules,
-  .nb_modules = CLI_DMI_MAX_MODULES,
+struct cli_module_descr dmi_show_modules = {
+       .modules = list_dmi_show_modules,
+       .default_callback = main_show_dmi,
 };
 
-struct commands_mode dmi_mode = {
-  .mode = DMI_MODE,
-  .show_modules = &dmi_show_modules,
+struct cli_mode_descr dmi_mode = {
+       .mode = DMI_MODE,
+       .name = CLI_DMI,
+       .default_modules = NULL,
+       .show_modules = &dmi_show_modules,
+       .set_modules = NULL,
 };
diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c
new file mode 100644 (file)
index 0000000..46f3669
--- /dev/null
@@ -0,0 +1,347 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslinux/config.h>
+
+#include "hdt-menu.h"
+#include "hdt-cli.h"
+#include "hdt-common.h"
+
+/**
+ * cli_clear_screen - clear (erase) the entire screen
+ **/
+static void cli_clear_screen(int argc __unused, char** argv __unused,
+                            struct s_hardware *hardware __unused)
+{
+       clear_screen();
+}
+
+/**
+ * main_show_modes - show availables modes
+ **/
+static void main_show_modes(int argc __unused, char** argv __unused,
+                           struct s_hardware *hardware __unused)
+{
+       int i = 0;
+
+       printf("Available modes:\n");
+       while (list_modes[i]) {
+               printf("\t%s\n", list_modes[i]->name);
+               i++;
+       }
+}
+
+/**
+ * cli_set_mode - set the mode of the cli, in the cli
+ *
+ * The mode number must be supplied in argv, position 0.
+ **/
+static void cli_set_mode(int argc, char **argv,
+                        struct s_hardware *hardware)
+{
+       cli_mode_t new_mode;
+
+       if (argc <= 0) {
+               printf("Which mode?\n");
+               return;
+       }
+
+       /*
+        * Note! argv[0] is a string representing the mode, we need the
+        * equivalent cli_mode_t to pass it to set_mode.
+        */
+       new_mode = mode_s_to_mode_t(argv[0]);
+       set_mode(new_mode, hardware);
+}
+
+/**
+ * do_exit - shared helper to exit a mode
+ **/
+static void do_exit(int argc __unused, char** argv __unused,
+                   struct s_hardware *hardware)
+{
+       int new_mode = HDT_MODE;
+
+       switch (hdt_cli.mode) {
+       case HDT_MODE:
+               new_mode = EXIT_MODE;
+               break;
+       default:
+               new_mode = HDT_MODE;
+               break;
+       }
+
+       dprintf("CLI DEBUG: Switching from mode %d to mode %d\n", hdt_cli.mode,
+                                                                 new_mode);
+       set_mode(new_mode, hardware);
+}
+
+/**
+ * show_cli_help - shared helper to show available commands
+ **/
+static void show_cli_help(int argc __unused, char** argv __unused,
+                         struct s_hardware *hardware __unused)
+{
+       int j = 0;
+       struct cli_mode_descr *current_mode;
+       struct cli_callback_descr* associated_module = NULL;
+
+       find_cli_mode_descr(hdt_cli.mode, &current_mode);
+
+       printf("Available commands are:\n");
+
+       /* List first default modules of the mode */
+       if (current_mode->default_modules &&
+           current_mode->default_modules->modules) {
+               while (current_mode->default_modules->modules[j].name) {
+                       printf("%s ",
+                              current_mode->default_modules->modules[j].name);
+                       j++;
+               }
+               printf("\n");
+       }
+
+       /* List secondly the show modules of the mode */
+       if (current_mode->show_modules &&
+           current_mode->show_modules->modules) {
+               printf("show commands:\n");
+               j = 0;
+               while (current_mode->show_modules->modules[j].name) {
+                       printf("\t%s\n",
+                              current_mode->show_modules->modules[j].name);
+                       j++;
+               }
+       }
+
+       /* List thirdly the set modules of the mode */
+       if (current_mode->set_modules &&
+           current_mode->set_modules->modules) {
+               printf("set commands:\n");
+               j = 0;
+               while (current_mode->set_modules->modules[j].name) {
+                       printf("\t%s\n",
+                              current_mode->set_modules->modules[j].name);
+                       j++;
+               }
+       }
+
+       /* List finally the default modules of the hdt mode */
+       if (current_mode->mode != hdt_mode.mode &&
+           hdt_mode.default_modules &&
+           hdt_mode.default_modules->modules) {
+               j = 0;
+               while (hdt_mode.default_modules->modules[j].name) {
+                       /*
+                        * Any default command that is present in hdt mode but
+                        * not in the current mode is available. A default
+                        * command can be redefined in the current mode though.
+                        * This next call test this use case: if it is
+                        * overwritten, do not print it again.
+                        */
+                       find_cli_callback_descr(hdt_mode.default_modules->modules[j].name,
+                                            current_mode->default_modules,
+                                            &associated_module);
+                       if (associated_module == NULL)
+                               printf("%s ",
+                                      hdt_mode.default_modules->modules[j].name);
+                       j++;
+               }
+               printf("\n");
+       }
+
+       main_show_modes(argc, argv, hardware);
+}
+
+/**
+ * show_cli_help - shared helper to show available commands
+ **/
+static void goto_menu(int argc __unused, char** argv __unused,
+                     struct s_hardware *hardware)
+{
+       char version_string[256];
+       snprintf(version_string, sizeof version_string, "%s %s by %s",
+                PRODUCT_NAME, VERSION, AUTHOR);
+       start_menu_mode(hardware, version_string);
+       return;
+}
+
+/**
+ * main_show_summary - give an overview of the system
+ **/
+void main_show_summary(int argc __unused, char **argv __unused,
+                      struct s_hardware *hardware)
+{
+       detect_pci(hardware);   /* pxe is detected in the pci */
+       detect_dmi(hardware);
+       cpu_detect(hardware);
+       clear_screen();
+       main_show_cpu(argc, argv, hardware);
+       if (hardware->is_dmi_valid) {
+               more_printf("System\n");
+               more_printf(" Manufacturer : %s\n",
+                           hardware->dmi.system.manufacturer);
+               more_printf(" Product Name : %s\n",
+                           hardware->dmi.system.product_name);
+               more_printf(" Serial       : %s\n",
+                           hardware->dmi.system.serial);
+               more_printf("Bios\n");
+               more_printf(" Version      : %s\n", hardware->dmi.bios.version);
+               more_printf(" Release      : %s\n",
+                           hardware->dmi.bios.release_date);
+
+               int argc = 2;
+               char *argv[2] = { "0", "0" };
+               show_dmi_memory_modules(argc, argv, hardware);
+       }
+       main_show_pci(argc, argv, hardware);
+
+       if (hardware->is_pxe_valid)
+               main_show_pxe(argc, argv, hardware);
+
+       main_show_kernel(argc, argv, hardware);
+}
+
+void main_show_hdt(int argc __unused, char **argv __unused,
+                  struct s_hardware *hardware __unused)
+{
+       printf("HDT\n");
+       printf(" Product     : %s\n", PRODUCT_NAME);
+       printf(" Version     : %s\n", VERSION);
+       printf(" Author      : %s\n", AUTHOR);
+       printf(" Contact     : %s\n", CONTACT);
+       char *contributors[NB_CONTRIBUTORS] = CONTRIBUTORS;
+       for (int c = 0; c < NB_CONTRIBUTORS; c++) {
+               printf(" Contributor : %s\n", contributors[c]);
+       }
+}
+
+/* Default hdt mode */
+struct cli_callback_descr list_hdt_default_modules[] = {
+       {
+               .name = CLI_CLEAR,
+               .exec = cli_clear_screen,
+       },
+       {
+               .name = CLI_EXIT,
+               .exec = do_exit,
+       },
+       {
+               .name = CLI_HELP,
+               .exec = show_cli_help,
+       },
+       {
+               .name = CLI_MENU,
+               .exec = goto_menu,
+       },
+       {
+               .name = NULL,
+               .exec = NULL
+       },
+};
+
+struct cli_callback_descr list_hdt_show_modules[] = {
+       {
+               .name = CLI_SUMMARY,
+               .exec = main_show_summary,
+       },
+       {
+               .name = CLI_PCI,
+               .exec = main_show_pci,
+       },
+       {
+               .name = CLI_DMI,
+               .exec = main_show_dmi,
+       },
+       {
+               .name = CLI_CPU,
+               .exec = main_show_cpu,
+       },
+       {
+               .name = CLI_PXE,
+               .exec = main_show_pxe,
+       },
+       {
+               .name = CLI_SYSLINUX,
+               .exec = main_show_syslinux,
+       },
+       {
+               .name = CLI_KERNEL,
+               .exec = main_show_kernel,
+       },
+       {
+               .name = CLI_VESA,
+               .exec = main_show_vesa,
+       },
+       {
+               .name = CLI_HDT,
+               .exec = main_show_hdt,
+       },
+       {
+               .name = "modes",
+               .exec = main_show_modes,
+       },
+       {
+               .name = NULL,
+               .exec = NULL,
+       },
+};
+
+struct cli_callback_descr list_hdt_set_modules[] = {
+       {
+               .name = CLI_MODE,
+               .exec = cli_set_mode,
+       },
+       {
+               .name = NULL,
+               .exec = NULL,
+       },
+};
+
+struct cli_module_descr hdt_default_modules = {
+       .modules = list_hdt_default_modules,
+};
+
+struct cli_module_descr hdt_show_modules = {
+       .modules = list_hdt_show_modules,
+       .default_callback = main_show_summary,
+};
+
+struct cli_module_descr hdt_set_modules = {
+       .modules = list_hdt_set_modules,
+};
+
+struct cli_mode_descr hdt_mode = {
+       .mode = HDT_MODE,
+       .name = CLI_HDT,
+       .default_modules = &hdt_default_modules,
+       .show_modules = &hdt_show_modules,
+       .set_modules = &hdt_set_modules,
+};
index 5b0df1d..d9ba27f 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
-void main_show_kernel(struct s_hardware *hardware)
+void main_show_kernel(int argc __unused, char **argv __unused,
+                     struct s_hardware *hardware)
 {
-  char buffer[1024];
-  struct pci_device *pci_device;
-  bool found = false;
-  char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
-          MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+       char buffer[1024];
+       struct pci_device *pci_device;
+       bool found = false;
+       char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
+                           MAX_KERNEL_MODULES_PER_PCI_DEVICE];
 
-  memset(buffer, 0, sizeof(buffer));
+       memset(buffer, 0, sizeof(buffer));
 
-  detect_pci(hardware);
-  more_printf("Kernel modules\n");
+       detect_pci(hardware);
+       more_printf("Kernel modules\n");
 
 // more_printf(" PCI device no: %d \n", p->pci_device_pos);
 
-  if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
-    more_printf(" modules.pcimap is missing\n");
-    return;
-  }
-
-  /* For every detected pci device, compute its submenu */
-  for_each_pci_func(pci_device, hardware->pci_domain) {
-    memset(kernel_modules, 0, sizeof kernel_modules);
-
-    for (int kmod = 0;
-         kmod < pci_device->dev_info->linux_kernel_module_count;
-         kmod++) {
-      if (kmod > 0) {
-        strncat(kernel_modules, " | ", 3);
-      }
-      strncat(kernel_modules,
-        pci_device->dev_info->linux_kernel_module[kmod],
-        LINUX_KERNEL_MODULE_SIZE - 1);
-    }
-
-    if ((pci_device->dev_info->linux_kernel_module_count > 0)
-        && (!strstr(buffer, kernel_modules))) {
-      found = true;
-      if (pci_device->dev_info->linux_kernel_module_count > 1)
-        strncat(buffer, "(", 1);
-      strncat(buffer, kernel_modules, sizeof(kernel_modules));
-      if (pci_device->dev_info->linux_kernel_module_count > 1)
-        strncat(buffer, ")", 1);
-      strncat(buffer, " # ", 3);
-    }
-
-  }
-  if (found == true) {
-    strncat(buffer, "\n", 1);
-    more_printf(buffer);
-  }
+       if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
+               more_printf(" modules.pcimap is missing\n");
+               return;
+       }
+
+       /* For every detected pci device, compute its submenu */
+       for_each_pci_func(pci_device, hardware->pci_domain) {
+               memset(kernel_modules, 0, sizeof kernel_modules);
+
+               for (int kmod = 0;
+                    kmod < pci_device->dev_info->linux_kernel_module_count;
+                    kmod++) {
+                       if (kmod > 0) {
+                               strncat(kernel_modules, " | ", 3);
+                       }
+                       strncat(kernel_modules,
+                               pci_device->dev_info->linux_kernel_module[kmod],
+                               LINUX_KERNEL_MODULE_SIZE - 1);
+               }
+
+               if ((pci_device->dev_info->linux_kernel_module_count > 0)
+                   && (!strstr(buffer, kernel_modules))) {
+                       found = true;
+                       if (pci_device->dev_info->linux_kernel_module_count > 1)
+                               strncat(buffer, "(", 1);
+                       strncat(buffer, kernel_modules, sizeof(kernel_modules));
+                       if (pci_device->dev_info->linux_kernel_module_count > 1)
+                               strncat(buffer, ")", 1);
+                       strncat(buffer, " # ", 3);
+               }
+
+       }
+       if (found == true) {
+               strncat(buffer, "\n", 1);
+               more_printf(buffer);
+       }
 }
 
-static void show_kernel_modules(struct s_hardware *hardware)
+static void show_kernel_modules(int argc __unused, char **argv __unused,
+                               struct s_hardware *hardware)
 {
-  struct pci_device *pci_device;
-  char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
-          MAX_KERNEL_MODULES_PER_PCI_DEVICE];
-  bool nopciids = false;
-  bool nomodulespcimap = false;
-  char modules[MAX_PCI_CLASSES][256];
-  char category_name[MAX_PCI_CLASSES][256];
-
-  detect_pci(hardware);
-  memset(&modules, 0, sizeof(modules));
-
-  if (hardware->pci_ids_return_code == -ENOPCIIDS) {
-    nopciids = true;
-    more_printf(" Missing pci.ids, we can't compute the list\n");
-    return;
-  }
-
-  if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
-    nomodulespcimap = true;
-    more_printf
-        (" Missing modules.pcimap, we can't compute the list\n");
-    return;
-  }
-
-  clear_screen();
-
-  for_each_pci_func(pci_device, hardware->pci_domain) {
-    memset(kernel_modules, 0, sizeof kernel_modules);
-
-    for (int kmod = 0;
-         kmod < pci_device->dev_info->linux_kernel_module_count;
-         kmod++) {
-      strncat(kernel_modules,
-        pci_device->dev_info->linux_kernel_module[kmod],
-        LINUX_KERNEL_MODULE_SIZE - 1);
-      strncat(kernel_modules, " ", 1);
-    }
-
-    if ((pci_device->dev_info->linux_kernel_module_count > 0)
-        && (!strstr(modules[pci_device->class[2]], kernel_modules)))
-    {
-      strncat(modules[pci_device->class[2]], kernel_modules,
-        sizeof(kernel_modules));
-      snprintf(category_name[pci_device->class[2]],
-         sizeof(category_name[pci_device->class[2]]),
-         "%s", pci_device->dev_info->category_name);
-    }
-  }
-  /* Print the found items */
-  for (int i = 0; i < MAX_PCI_CLASSES; i++) {
-    if (strlen(category_name[i]) > 1) {
-      more_printf("%s : %s\n", category_name[i], modules[i]);
-    }
-  }
+       struct pci_device *pci_device;
+       char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
+                           MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+       bool nopciids = false;
+       bool nomodulespcimap = false;
+       char modules[MAX_PCI_CLASSES][256];
+       char category_name[MAX_PCI_CLASSES][256];
+
+       detect_pci(hardware);
+       memset(&modules, 0, sizeof(modules));
+
+       if (hardware->pci_ids_return_code == -ENOPCIIDS) {
+               nopciids = true;
+               printf(" Missing pci.ids, we can't compute the list\n");
+               return;
+       }
+
+       if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
+               nomodulespcimap = true;
+               printf
+                   (" Missing modules.pcimap, we can't compute the list\n");
+               return;
+       }
+
+       for_each_pci_func(pci_device, hardware->pci_domain) {
+               memset(kernel_modules, 0, sizeof kernel_modules);
+
+               for (int kmod = 0;
+                    kmod < pci_device->dev_info->linux_kernel_module_count;
+                    kmod++) {
+                       strncat(kernel_modules,
+                               pci_device->dev_info->linux_kernel_module[kmod],
+                               LINUX_KERNEL_MODULE_SIZE - 1);
+                       strncat(kernel_modules, " ", 1);
+               }
+
+               if ((pci_device->dev_info->linux_kernel_module_count > 0)
+                   && (!strstr(modules[pci_device->class[2]], kernel_modules))) {
+                       strncat(modules[pci_device->class[2]], kernel_modules,
+                               sizeof(kernel_modules));
+                       snprintf(category_name[pci_device->class[2]],
+                                sizeof(category_name[pci_device->class[2]]),
+                                "%s", pci_device->dev_info->category_name);
+               }
+       }
+       /* Print the found items */
+       for (int i = 0; i < MAX_PCI_CLASSES; i++) {
+               if (strlen(category_name[i]) > 1) {
+                       printf("%s : %s\n", category_name[i], modules[i]);
+               }
+       }
 }
 
-static void show_kernel_help()
-{
-  more_printf("Show supports the following commands : %s\n",
-              CLI_SHOW_LIST);
-}
-
-void kernel_show(char *item, struct s_hardware *hardware)
-{
-  if (!strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1)) {
-    show_kernel_modules(hardware);
-    return;
-  }
-  show_kernel_help();
-}
-
-void handle_kernel_commands(char *cli_line, struct s_hardware *hardware)
-{
-  if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-    kernel_show(strstr(cli_line, "show") + sizeof(CLI_SHOW),
-          hardware);
-    return;
-  }
-}
+struct cli_module_descr kernel_show_modules = {
+       .modules = NULL,
+       .default_callback = show_kernel_modules,
+};
+
+struct cli_mode_descr kernel_mode = {
+       .mode = KERNEL_MODE,
+       .name = CLI_KERNEL,
+       .default_modules = NULL,
+       .show_modules = &kernel_show_modules,
+       .set_modules = NULL,
+};
index 31cfe77..1213c32 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
-void show_pci_device(struct s_hardware *hardware, const char *item)
+void main_show_pci(int argc __unused, char **argv __unused,
+                  struct s_hardware *hardware)
 {
-  int i = 0;
-  struct pci_device *pci_device = NULL, *temp_pci_device;
-  long pcidev = strtol(item, (char **)NULL, 10);
-  bool nopciids = false;
-  bool nomodulespcimap = false;
-  char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
-          MAX_KERNEL_MODULES_PER_PCI_DEVICE];
-  int bus = 0, slot = 0, func = 0;
+       cli_detect_pci(hardware);
 
-  if (errno == ERANGE) {
-    printf("This PCI device number is incorrect\n");
-    return;
-  }
-  if ((pcidev > hardware->nb_pci_devices) || (pcidev <= 0)) {
-    printf("PCI device %d  doesn't exists\n", pcidev);
-    return;
-  }
-  if (hardware->pci_ids_return_code == -ENOPCIIDS) {
-    nopciids = true;
-  }
-  if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
-    nomodulespcimap = true;
-  }
+       more_printf("PCI\n");
+       more_printf(" NB Devices   : %d\n", hardware->nb_pci_devices);
+}
+
+static void show_pci_device(int argc, char **argv,
+                           struct s_hardware *hardware)
+{
+       int i = 0;
+       struct pci_device *pci_device = NULL, *temp_pci_device;
+       int pcidev = -1;
+       bool nopciids = false;
+       bool nomodulespcimap = false;
+       char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
+                           MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+       int bus = 0, slot = 0, func = 0;
+
+       /* Sanitize arguments */
+       if (argc <= 0) {
+               printf("show device <number>\n");
+               return;
+       } else
+               pcidev = strtol(argv[0], (char **)NULL, 10);
 
-  for_each_pci_func(temp_pci_device, hardware->pci_domain) {
-    i++;
-    if (i == pcidev) {
-      bus = __pci_bus;
-      slot = __pci_slot;
-      func = __pci_func;
-      pci_device = temp_pci_device;
-    }
-  }
+       if (errno == ERANGE) {
+               printf("This PCI device number is incorrect\n");
+               return;
+       }
+       if ((pcidev > hardware->nb_pci_devices) || (pcidev <= 0)) {
+               printf("PCI device %d doesn't exists\n", pcidev);
+               return;
+       }
+       if (hardware->pci_ids_return_code == -ENOPCIIDS) {
+               nopciids = true;
+       }
+       if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
+               nomodulespcimap = true;
+       }
 
-  if (pci_device == NULL) {
-    printf("We were enabled to find PCI device %d\n", pcidev);
-    return;
-  }
+       for_each_pci_func(temp_pci_device, hardware->pci_domain) {
+               i++;
+               if (i == pcidev) {
+                       bus = __pci_bus;
+                       slot = __pci_slot;
+                       func = __pci_func;
+                       pci_device = temp_pci_device;
+               }
+       }
 
-  memset(kernel_modules, 0, sizeof kernel_modules);
-  for (int kmod = 0;
-       kmod < pci_device->dev_info->linux_kernel_module_count; kmod++) {
-    if (kmod > 0) {
-      strncat(kernel_modules, " | ", 3);
-    }
-    strncat(kernel_modules,
-      pci_device->dev_info->linux_kernel_module[kmod],
-      LINUX_KERNEL_MODULE_SIZE - 1);
-  }
-  if (pci_device->dev_info->linux_kernel_module_count == 0)
-    strlcpy(kernel_modules, "unknown", 7);
+       if (pci_device == NULL) {
+               printf("We were enabled to find PCI device %d\n", pcidev);
+               return;
+       }
 
-  clear_screen();
-  printf("PCI Device %d\n", pcidev);
+       memset(kernel_modules, 0, sizeof kernel_modules);
+       for (int kmod = 0;
+            kmod < pci_device->dev_info->linux_kernel_module_count; kmod++) {
+               if (kmod > 0) {
+                       strncat(kernel_modules, " | ", 3);
+               }
+               strncat(kernel_modules,
+                       pci_device->dev_info->linux_kernel_module[kmod],
+                       LINUX_KERNEL_MODULE_SIZE - 1);
+       }
+       if (pci_device->dev_info->linux_kernel_module_count == 0)
+               strlcpy(kernel_modules, "unknown", 7);
 
-  if (nopciids == false) {
-    more_printf("Vendor Name   : %s\n",
-          pci_device->dev_info->vendor_name);
-    more_printf("Product Name  : %s\n",
-          pci_device->dev_info->product_name);
-    more_printf("Class Name    : %s\n",
-          pci_device->dev_info->class_name);
-  }
+       printf("PCI Device %d\n", pcidev);
 
-  if (nomodulespcimap == false) {
-    more_printf("Kernel module : %s\n", kernel_modules);
-  }
+       if (nopciids == false) {
+               printf("Vendor Name   : %s\n",
+                           pci_device->dev_info->vendor_name);
+               printf("Product Name  : %s\n",
+                           pci_device->dev_info->product_name);
+               printf("Class Name    : %s\n",
+                           pci_device->dev_info->class_name);
+       }
 
-  more_printf("Vendor ID     : %04x\n", pci_device->vendor);
-  more_printf("Product ID    : %04x\n", pci_device->product);
-  more_printf("SubVendor ID  : %04x\n", pci_device->sub_vendor);
-  more_printf("SubProduct ID : %04x\n", pci_device->sub_product);
-  more_printf("Class ID      : %02x.%02x.%02x\n", pci_device->class[2],
-        pci_device->class[1], pci_device->class[0]);
-  more_printf("Revision      : %02x\n", pci_device->revision);
-  if ((pci_device->dev_info->irq > 0)
-      && (pci_device->dev_info->irq < 255))
-    more_printf("IRQ           : %0d\n", pci_device->dev_info->irq);
-  more_printf("Latency       : %0d\n",pci_device->dev_info->latency);
-  more_printf("PCI Bus       : %02d\n", bus);
-  more_printf("PCI Slot      : %02d\n", slot);
-  more_printf("PCI Func      : %02d\n", func);
+       if (nomodulespcimap == false) {
+               printf("Kernel module : %s\n", kernel_modules);
+       }
 
-  if (hardware->is_pxe_valid == true) {
-    more_printf("Mac Address   : %s\n", hardware->pxe.mac_addr);
-    if ((hardware->pxe.pci_device != NULL)
-        && (hardware->pxe.pci_device == pci_device))
-      more_printf("PXE           : Current boot device\n",
-            func);
-  }
+       printf("Vendor ID     : %04x\n", pci_device->vendor);
+       printf("Product ID    : %04x\n", pci_device->product);
+       printf("SubVendor ID  : %04x\n", pci_device->sub_vendor);
+       printf("SubProduct ID : %04x\n", pci_device->sub_product);
+       printf("Class ID      : %02x.%02x.%02x\n", pci_device->class[2],
+                   pci_device->class[1], pci_device->class[0]);
+       printf("Revision      : %02x\n", pci_device->revision);
+       if ((pci_device->dev_info->irq > 0)
+           && (pci_device->dev_info->irq < 255))
+               more_printf("IRQ           : %0d\n", pci_device->dev_info->irq);
+       printf("Latency       : %0d\n", pci_device->dev_info->latency);
+       printf("PCI Bus       : %02d\n", bus);
+       printf("PCI Slot      : %02d\n", slot);
+       printf("PCI Func      : %02d\n", func);
+
+       if (hardware->is_pxe_valid == true) {
+               if ((hardware->pxe.pci_device != NULL)
+                   && (hardware->pxe.pci_device == pci_device)) {
+                       printf("Mac Address   : %s\n", hardware->pxe.mac_addr);
+                       printf("PXE           : Current boot device\n");
+               }
+       }
 }
 
-static void show_pci_devices(struct s_hardware *hardware)
+static void show_pci_devices(int argc __unused, char **argv __unused,
+                            struct s_hardware *hardware)
 {
-  int i = 1;
-  struct pci_device *pci_device;
-  char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
-          MAX_KERNEL_MODULES_PER_PCI_DEVICE];
-  bool nopciids = false;
-  bool nomodulespcimap = false;
-  char first_line[81];
-  char second_line[81];
-
-  clear_screen();
-  more_printf("%d PCI devices detected\n", hardware->nb_pci_devices);
+       int i = 1;
+       struct pci_device *pci_device;
+       char kernel_modules[LINUX_KERNEL_MODULE_SIZE *
+                           MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+       bool nopciids = false;
+       bool nomodulespcimap = false;
+       char first_line[81];
+       char second_line[81];
 
-  if (hardware->pci_ids_return_code == -ENOPCIIDS) {
-    nopciids = true;
-  }
-  if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
-    nomodulespcimap = true;
-  }
+       reset_more_printf();
+       more_printf("%d PCI devices detected\n", hardware->nb_pci_devices);
 
-  /* For every detected pci device, compute its submenu */
-  for_each_pci_func(pci_device, hardware->pci_domain) {
-    memset(kernel_modules, 0, sizeof kernel_modules);
-    for (int kmod = 0;
-         kmod < pci_device->dev_info->linux_kernel_module_count;
-         kmod++) {
-      if (kmod > 0) {
-        strncat(kernel_modules, " | ", 3);
-      }
-      strncat(kernel_modules,
-        pci_device->dev_info->linux_kernel_module[kmod],
-        LINUX_KERNEL_MODULE_SIZE - 1);
-    }
-    if (pci_device->dev_info->linux_kernel_module_count == 0)
-      strlcpy(kernel_modules, "unknown", 7);
+       if (hardware->pci_ids_return_code == -ENOPCIIDS) {
+               nopciids = true;
+       }
+       if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
+               nomodulespcimap = true;
+       }
 
-    if (nopciids == false) {
-      snprintf(first_line, sizeof(first_line),
-         "%02d: %s %s \n", i,
-         pci_device->dev_info->vendor_name,
-         pci_device->dev_info->product_name);
-      if (nomodulespcimap == false)
-        snprintf(second_line, sizeof(second_line),
-           "    # %-25s # Kmod: %s\n",
-           pci_device->dev_info->class_name,
-           kernel_modules);
-      else
-        snprintf(second_line, sizeof(second_line),
-           "    # %-25s # ID:%04x:%04x[%04x:%04x]\n",
-           pci_device->dev_info->class_name,
-           pci_device->vendor,
-           pci_device->product,
-           pci_device->sub_vendor,
-           pci_device->sub_product);
+       /* For every detected pci device, compute its submenu */
+       for_each_pci_func(pci_device, hardware->pci_domain) {
+               memset(kernel_modules, 0, sizeof kernel_modules);
+               for (int kmod = 0;
+                    kmod < pci_device->dev_info->linux_kernel_module_count;
+                    kmod++) {
+                       if (kmod > 0) {
+                               strncat(kernel_modules, " | ", 3);
+                       }
+                       strncat(kernel_modules,
+                               pci_device->dev_info->linux_kernel_module[kmod],
+                               LINUX_KERNEL_MODULE_SIZE - 1);
+               }
+               if (pci_device->dev_info->linux_kernel_module_count == 0)
+                       strlcpy(kernel_modules, "unknown", 7);
 
-      more_printf(first_line);
-      more_printf(second_line);
-      more_printf("\n");
-    } else if (nopciids == true) {
-      if (nomodulespcimap == true) {
-        more_printf("%02d: %04x:%04x [%04x:%04x] \n",
-              i, pci_device->vendor,
-              pci_device->product,
-              pci_device->sub_vendor,
-              pci_device->sub_product);
-      } else {
-        more_printf
-            ("%02d: %04x:%04x [%04x:%04x] Kmod:%s\n", i,
-             pci_device->vendor, pci_device->product,
-             pci_device->sub_vendor,
-             pci_device->sub_product, kernel_modules,
-             pci_device->sub_product, kernel_modules);
-      }
-    }
-    i++;
-  }
+               if (nopciids == false) {
+                       snprintf(first_line, sizeof(first_line),
+                                "%02d: %s %s \n", i,
+                                pci_device->dev_info->vendor_name,
+                                pci_device->dev_info->product_name);
+                       if (nomodulespcimap == false)
+                               snprintf(second_line, sizeof(second_line),
+                                        "    # %-25s # Kmod: %s\n",
+                                        pci_device->dev_info->class_name,
+                                        kernel_modules);
+                       else
+                               snprintf(second_line, sizeof(second_line),
+                                        "    # %-25s # ID:%04x:%04x[%04x:%04x]\n",
+                                        pci_device->dev_info->class_name,
+                                        pci_device->vendor,
+                                        pci_device->product,
+                                        pci_device->sub_vendor,
+                                        pci_device->sub_product);
 
+                       more_printf(first_line);
+                       more_printf(second_line);
+                       more_printf("\n");
+               } else if (nopciids == true) {
+                       if (nomodulespcimap == true) {
+                               more_printf("%02d: %04x:%04x [%04x:%04x] \n",
+                                           i, pci_device->vendor,
+                                           pci_device->product,
+                                           pci_device->sub_vendor,
+                                           pci_device->sub_product);
+                       } else {
+                               more_printf
+                                   ("%02d: %04x:%04x [%04x:%04x] Kmod:%s\n", i,
+                                    pci_device->vendor, pci_device->product,
+                                    pci_device->sub_vendor,
+                                    pci_device->sub_product, kernel_modules);
+                       }
+               }
+               i++;
+       }
 }
 
-static void show_pci_irq(struct s_hardware *hardware)
+static void show_pci_irq(int argc __unused, char **argv __unused,
+                        struct s_hardware *hardware)
 {
-  struct pci_device *pci_device;
-  bool nopciids = false;
+       struct pci_device *pci_device;
+       bool nopciids = false;
 
-  clear_screen();
-  more_printf("%d PCI devices detected\n", hardware->nb_pci_devices);
-  more_printf("IRQ : product\n");
-  more_printf("-------------\n");
+       reset_more_printf();
+       more_printf("%d PCI devices detected\n", hardware->nb_pci_devices);
+       more_printf("IRQ : product\n");
+       more_printf("-------------\n");
 
-  if (hardware->pci_ids_return_code == -ENOPCIIDS) {
-    nopciids = true;
-  }
+       if (hardware->pci_ids_return_code == -ENOPCIIDS) {
+               nopciids = true;
+       }
 
-  /* For every detected pci device, compute its submenu */
-  for_each_pci_func(pci_device, hardware->pci_domain) {
-    /* Only display valid IRQs */
-    if ((pci_device->dev_info->irq > 0) && (pci_device->dev_info->irq < 255)) {
-      if (nopciids == false) {
-        more_printf("%02d  : %s %s \n",
-              pci_device->dev_info->irq,
-              pci_device->dev_info->vendor_name,
-              pci_device->dev_info->product_name);
-      } else {
-        more_printf("%02d  : %04x:%04x [%04x:%04x] \n",
-              pci_device->dev_info->irq, pci_device->vendor,
-              pci_device->product,
-              pci_device->sub_vendor,
-              pci_device->sub_product);
-      }
-    }
-  }
+       /* For every detected pci device, compute its submenu */
+       for_each_pci_func(pci_device, hardware->pci_domain) {
+               /* Only display valid IRQs */
+               if ((pci_device->dev_info->irq > 0)
+                   && (pci_device->dev_info->irq < 255)) {
+                       if (nopciids == false) {
+                               more_printf("%02d  : %s %s \n",
+                                           pci_device->dev_info->irq,
+                                           pci_device->dev_info->vendor_name,
+                                           pci_device->dev_info->product_name);
+                       } else {
+                               more_printf("%02d  : %04x:%04x [%04x:%04x] \n",
+                                           pci_device->dev_info->irq,
+                                           pci_device->vendor,
+                                           pci_device->product,
+                                           pci_device->sub_vendor,
+                                           pci_device->sub_product);
+                       }
+               }
+       }
 }
 
-static void show_pci_help()
-{
-  more_printf("Show supports the following commands : \n");
-  more_printf(" %s\n", CLI_SHOW_LIST);
-  more_printf(" %s <device_number>\n", CLI_PCI_DEVICE);
-  more_printf(" %s\n",CLI_IRQ);
-}
+struct cli_callback_descr list_pci_show_modules[] = {
+       {
+        .name = CLI_IRQ,
+        .exec = show_pci_irq,
+        },
+       {
+        .name = CLI_PCI_DEVICE,
+        .exec = show_pci_device,
+        },
+       {
+        .name = NULL,
+        .exec = NULL,
+        },
+};
 
-static void pci_show(char *item, struct s_hardware *hardware)
-{
-  if (!strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1)) {
-    show_pci_devices(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_IRQ, sizeof(CLI_IRQ) - 1)) {
-    show_pci_irq(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_PCI_DEVICE, sizeof(CLI_PCI_DEVICE) - 1)) {
-    show_pci_device(hardware, item + sizeof(CLI_PCI_DEVICE) - 1);
-    return;
-  }
-  show_pci_help();
-}
+struct cli_module_descr pci_show_modules = {
+       .modules = list_pci_show_modules,
+       .default_callback = show_pci_devices,
+};
 
-void handle_pci_commands(char *cli_line, struct s_hardware *hardware)
-{
-  if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-    pci_show(strstr(cli_line, "show") + sizeof(CLI_SHOW), hardware);
-    return;
-  }
-}
+struct cli_mode_descr pci_mode = {
+       .mode = PCI_MODE,
+       .name = CLI_PCI,
+       .default_modules = NULL,
+       .show_modules = &pci_show_modules,
+       .set_modules = NULL,
+};
 
 void cli_detect_pci(struct s_hardware *hardware)
 {
-  bool error = false;
-  if (hardware->pci_detection == false) {
-    detect_pci(hardware);
-    if (hardware->pci_ids_return_code == -ENOPCIIDS) {
-      more_printf
-          ("The pci.ids file is missing, device names can't be computed.\n");
-      more_printf("Please put one in same dir as hdt\n");
-      error = true;
-    }
-    if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
-      more_printf
-          ("The modules.pcimap file is missing, device names can't be computed.\n");
-      more_printf("Please put one in same dir as hdt\n");
-      error = true;
-    }
-    if (error == true) {
-      char tempbuf[10];
-      printf("Press enter to continue\n");
-      fgets(tempbuf, sizeof(tempbuf), stdin);
-    }
-  }
-}
-
-void main_show_pci(struct s_hardware *hardware)
-{
-  cli_detect_pci(hardware);
-
-  more_printf("PCI\n");
-  more_printf(" NB Devices   : %d\n", hardware->nb_pci_devices);
+       bool error = false;
+       if (hardware->pci_detection == false) {
+               detect_pci(hardware);
+               if (hardware->pci_ids_return_code == -ENOPCIIDS) {
+                       printf
+                           ("The pci.ids file is missing, device names can't be computed.\n");
+                       printf("Please put one in same dir as hdt\n");
+                       error = true;
+               }
+               if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) {
+                       printf
+                           ("The modules.pcimap file is missing, device names can't be computed.\n");
+                       printf("Please put one in same dir as hdt\n");
+                       error = true;
+               }
+               if (error == true) {
+                       char tempbuf[10];
+                       printf("Press enter to continue\n");
+                       fgets(tempbuf, sizeof(tempbuf), stdin);
+               }
+       }
 }
index 5c55664..1d00cae 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
-void main_show_pxe(struct s_hardware *hardware)
+void main_show_pxe(int argc __unused, char **argv __unused,
+                  struct s_hardware *hardware)
 {
-  char buffer[81];
-  memset(buffer, 0, sizeof(81));
-  if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) {
-    more_printf("You are not currently using PXELINUX\n");
-    return;
-  }
+       char buffer[81];
+       memset(buffer, 0, sizeof(81));
+       if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) {
+               printf("You are not currently using PXELINUX\n");
+               return;
+       }
 
-  detect_pxe(hardware);
-  more_printf("PXE\n");
-  if (hardware->is_pxe_valid == false) {
-    more_printf(" No valid PXE ROM found\n");
-    return;
-  }
+       detect_pxe(hardware);
+       printf("PXE\n");
+       if (hardware->is_pxe_valid == false) {
+               printf(" No valid PXE ROM found\n");
+               return;
+       }
 
-  struct s_pxe *p = &hardware->pxe;
-  more_printf(" PCI device no: %d \n", p->pci_device_pos);
+       struct s_pxe *p = &hardware->pxe;
+       printf(" PCI device no: %d \n", p->pci_device_pos);
 
-  if ((hardware->pci_ids_return_code == -ENOPCIIDS) ||  (p->pci_device==NULL)) {
-    snprintf(buffer, sizeof(buffer),
-       " PCI ID       : %04x:%04x[%04x:%04X] rev(%02x)\n",
-       p->vendor_id, p->product_id, p->subvendor_id,
-       p->subproduct_id, p->rev);
-    snprintf(buffer, sizeof(buffer),
-       " PCI Bus pos. : %02x:%02x.%02x\n", p->pci_bus,
-       p->pci_dev, p->pci_func);
-    more_printf(buffer);
-  } else {
-    snprintf(buffer, sizeof(buffer), " Manufacturer : %s \n",
-       p->pci_device->dev_info->vendor_name);
-    more_printf(buffer);
-    snprintf(buffer, sizeof(buffer), " Product      : %s \n",
-       p->pci_device->dev_info->product_name);
-    more_printf(buffer);
-  }
-  more_printf(" Addresses    : %d.%d.%d.%d @ %s\n", p->ip_addr[0],
-        p->ip_addr[1], p->ip_addr[2], p->ip_addr[3], p->mac_addr);
+       if (hardware->pci_ids_return_code == -ENOPCIIDS ||
+           (p->pci_device == NULL)) {
+               snprintf(buffer, sizeof(buffer),
+                        " PCI ID       : %04x:%04x[%04x:%04X] rev(%02x)\n",
+                        p->vendor_id, p->product_id, p->subvendor_id,
+                        p->subproduct_id, p->rev);
+               snprintf(buffer, sizeof(buffer),
+                        " PCI Bus pos. : %02x:%02x.%02x\n", p->pci_bus,
+                        p->pci_dev, p->pci_func);
+               printf(buffer);
+       } else {
+               snprintf(buffer, sizeof(buffer), " Manufacturer : %s \n",
+                        p->pci_device->dev_info->vendor_name);
+               printf(buffer);
+               snprintf(buffer, sizeof(buffer), " Product      : %s \n",
+                        p->pci_device->dev_info->product_name);
+               printf(buffer);
+       }
+       printf(" Addresses    : %d.%d.%d.%d @ %s\n", p->ip_addr[0],
+                   p->ip_addr[1], p->ip_addr[2], p->ip_addr[3], p->mac_addr);
 }
 
-static void show_pxe_help()
-{
-  more_printf("Show supports the following commands : %s\n",
-        CLI_SHOW_LIST);
-}
+struct cli_module_descr pxe_show_modules = {
+       .modules = NULL,
+       .default_callback = main_show_pxe,
+};
 
-static void pxe_show(char *item, struct s_hardware *hardware)
-{
-  if (!strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1)) {
-    main_show_pxe(hardware);
-    return;
-  }
-  show_pxe_help();
-}
-
-void handle_pxe_commands(char *cli_line, struct s_hardware *hardware)
-{
-  if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-    pxe_show(strstr(cli_line, "show") + sizeof(CLI_SHOW), hardware);
-    return;
-  }
-}
+struct cli_mode_descr pxe_mode = {
+       .mode = PXE_MODE,
+       .name = CLI_PXE,
+       .default_modules = NULL,
+       .show_modules = &pxe_show_modules,
+       .set_modules = NULL,
+};
index 77a44f3..0d78bc6 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
-void main_show_syslinux(struct s_hardware *hardware)
+void main_show_syslinux(int argc __unused, char **argv __unused,
+                       struct s_hardware *hardware)
 {
-  more_printf("SYSLINUX\n");
-  more_printf(" Bootloader : %s\n", hardware->syslinux_fs);
-  more_printf(" Version    : %s\n", hardware->sv->version_string + 2);
-  more_printf(" Version    : %u\n", hardware->sv->version);
-  more_printf(" Max API    : %u\n", hardware->sv->max_api);
-  more_printf(" Copyright  : %s\n", hardware->sv->copyright_string + 1);
+  printf("SYSLINUX\n");
+  printf(" Bootloader : %s\n", hardware->syslinux_fs);
+  printf(" Version    : %s\n", hardware->sv->version_string + 2);
+  printf(" Version    : %u\n", hardware->sv->version);
+  printf(" Max API    : %u\n", hardware->sv->max_api);
+  printf(" Copyright  : %s\n", hardware->sv->copyright_string + 1);
 }
 
-static void show_syslinux_help()
-{
-  more_printf("Show supports the following commands : %s\n",
-              CLI_SHOW_LIST);
-}
+struct cli_module_descr syslinux_show_modules = {
+       .modules = NULL,
+       .default_callback = main_show_syslinux,
+};
 
-static void syslinux_show(char *item, struct s_hardware *hardware)
-{
-  if (!strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1)) {
-    main_show_syslinux(hardware);
-    return;
-  }
-  show_syslinux_help();
-}
-
-void handle_syslinux_commands(char *cli_line, struct s_hardware *hardware)
-{
-  if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-    syslinux_show(strstr(cli_line, "show") + sizeof(CLI_SHOW),
-                  hardware);
-    return;
-  }
-}
+struct cli_mode_descr syslinux_mode = {
+       .mode = SYSLINUX_MODE,
+       .name = CLI_SYSLINUX,
+       .default_modules = NULL,
+       .show_modules = &syslinux_show_modules,
+       .set_modules = NULL,
+};
index 202b75f..70d1dc6 100644 (file)
 #include <stdlib.h>
 #include <errno.h>
 
-void main_show_vesa(struct s_hardware *hardware) {
-  detect_vesa(hardware);
-  if (hardware->is_vesa_valid==false) {
-    more_printf("No VESA BIOS detected\n");
-    return;
-  }
-  more_printf("VESA\n");
-  more_printf(" Vesa version : %d.%d\n",hardware->vesa.major_version, hardware->vesa.minor_version);
-  more_printf(" Vendor       : %s\n",hardware->vesa.vendor);
-  more_printf(" Product      : %s\n",hardware->vesa.product);
-  more_printf(" Product rev. : %s\n",hardware->vesa.product_revision);
-  more_printf(" Software rev.: %d\n",hardware->vesa.software_rev);
-  more_printf(" Memory (KB)  : %d\n",hardware->vesa.total_memory*64);
-  more_printf(" Modes        : %d\n",hardware->vesa.vmi_count);
+void main_show_vesa(int argc __unused, char **argv __unused,
+                   struct s_hardware *hardware)
+{
+       detect_vesa(hardware);
+       if (hardware->is_vesa_valid == false) {
+               printf("No VESA BIOS detected\n");
+               return;
+       }
+       printf("VESA\n");
+       printf(" Vesa version : %d.%d\n", hardware->vesa.major_version,
+                   hardware->vesa.minor_version);
+       printf(" Vendor       : %s\n", hardware->vesa.vendor);
+       printf(" Product      : %s\n", hardware->vesa.product);
+       printf(" Product rev. : %s\n", hardware->vesa.product_revision);
+       printf(" Software rev.: %d\n", hardware->vesa.software_rev);
+       printf(" Memory (KB)  : %d\n", hardware->vesa.total_memory * 64);
+       printf(" Modes        : %d\n", hardware->vesa.vmi_count);
 }
 
-void show_vesa_modes(struct s_hardware *hardware) {
-  detect_vesa(hardware);
-  if (hardware->is_vesa_valid==false) {
-    more_printf("No VESA BIOS detected\n");
-    return;
-  }
-  clear_screen();
-  more_printf(" ResH. x ResV x Bits : vga= : Vesa Mode\n",hardware->vesa.vmi_count);
-  more_printf("----------------------------------------\n",hardware->vesa.vmi_count);
+static void show_vesa_modes(int argc __unused, char **argv __unused,
+                           struct s_hardware *hardware)
+{
+       detect_vesa(hardware);
+       if (hardware->is_vesa_valid == false) {
+               printf("No VESA BIOS detected\n");
+               return;
+       }
+       reset_more_printf();
+       printf(" ResH. x ResV x Bits : vga= : Vesa Mode\n");
+       printf("----------------------------------------\n");
 
-  for (int i=0;i<hardware->vesa.vmi_count;i++) {
-    struct vesa_mode_info *mi=&hardware->vesa.vmi[i].mi;
-    /* Sometimes, vesa bios reports 0x0 modes
-     * We don't need to display that ones */
-    if ((mi->h_res==0) || (mi->v_res==0)) continue;
-    more_printf("%5u %5u    %3u     %3d     0x%04x\n",
-                 mi->h_res, mi->v_res, mi->bpp, hardware->vesa.vmi[i].mode+0x200,hardware->vesa.vmi[i].mode);
-  }
+       for (int i = 0; i < hardware->vesa.vmi_count; i++) {
+               struct vesa_mode_info *mi = &hardware->vesa.vmi[i].mi;
+               /*
+                * Sometimes, vesa bios reports 0x0 modes.
+                * We don't need to display that ones.
+                */
+               if ((mi->h_res == 0) || (mi->v_res == 0)) continue;
+               printf("%5u %5u    %3u     %3d     0x%04x\n",
+                           mi->h_res, mi->v_res, mi->bpp,
+                           hardware->vesa.vmi[i].mode + 0x200,
+                           hardware->vesa.vmi[i].mode);
+       }
 }
 
-static void show_vesa_help() {
- more_printf("Show supports the following commands : %s %s\n",CLI_SHOW_LIST, CLI_MODES);
-}
-
-static void vesa_show(char *item, struct s_hardware *hardware) {
- if ( !strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1) ) {
-   main_show_vesa(hardware);
-   return;
- }
- if ( !strncmp(item, CLI_MODES, sizeof(CLI_MODES) - 1) ) {
-   show_vesa_modes(hardware);
-   return;
- }
- show_vesa_help();
-}
+struct cli_callback_descr list_vesa_show_modules[] = {
+       {
+        .name = CLI_MODES,
+        .exec = show_vesa_modes,
+        },
+       {
+        .name = NULL,
+        .exec = NULL,
+        },
+};
 
-void handle_vesa_commands(char *cli_line, struct s_hardware *hardware) {
- if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) {
-    vesa_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware);
-    return;
- }
-}
+struct cli_module_descr vesa_show_modules = {
+       .modules = list_vesa_show_modules,
+       .default_callback = main_show_vesa,
+};
 
+struct cli_mode_descr vesa_mode = {
+       .mode = VESA_MODE,
+       .name = CLI_VESA,
+       .default_modules = NULL,
+       .show_modules = &vesa_show_modules,
+       .set_modules = NULL,
+};
diff --git a/com32/hdt/hdt-cli-vpd.c b/com32/hdt/hdt-cli-vpd.c
new file mode 100644 (file)
index 0000000..03614d3
--- /dev/null
@@ -0,0 +1,74 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+ */
+
+#include <string.h>
+#include <vpd/vpd.h>
+
+#include "hdt-cli.h"
+#include "hdt-common.h"
+
+void main_show_vpd(int argc __unused, char **argv __unused,
+                  struct s_hardware *hardware)
+{
+       reset_more_printf();
+       detect_vpd(hardware);
+
+       if (!hardware->is_vpd_valid) {
+               printf("No VPD structure detected.\n");
+               return;
+       }
+
+       printf("VPD present at address : 0x%s\n", hardware->vpd.base_address);
+       if (strlen(hardware->vpd.bios_build_id) > 0)
+               more_printf("Bios Build ID                 : %s\n", hardware->vpd.bios_build_id);
+       if (strlen(hardware->vpd.bios_release_date) > 0)
+               more_printf("Bios Release Date             : %s\n", hardware->vpd.bios_release_date);
+       if (strlen(hardware->vpd.bios_version) > 0)
+               more_printf("Bios Version                  : %s\n", hardware->vpd.bios_version);
+       if (strlen(hardware->vpd.default_flash_filename) > 0)
+               more_printf("Default Flash Filename        : %s\n", hardware->vpd.default_flash_filename);
+       if (strlen(hardware->vpd.box_serial_number) > 0)
+               more_printf("Box Serial Number             : %s\n", hardware->vpd.box_serial_number);
+       if (strlen(hardware->vpd.motherboard_serial_number) > 0)
+               more_printf("Motherboard Serial Number     : %s\n", hardware->vpd.motherboard_serial_number);
+       if (strlen(hardware->vpd.machine_type_model) > 0)
+               more_printf("Machine Type/Model            : %s\n", hardware->vpd.machine_type_model);
+}
+
+struct cli_module_descr vpd_show_modules = {
+       .modules = NULL,
+       .default_callback = main_show_vpd,
+};
+
+struct cli_mode_descr vpd_mode = {
+       .mode = VPD_MODE,
+       .name = CLI_VPD,
+       .default_modules = NULL,
+       .show_modules = &vpd_show_modules,
+       .set_modules = NULL,
+};
index 8e71690..871fd76 100644 (file)
 #include <getkey.h>
 #include "hdt-cli.h"
 #include "hdt-common.h"
+#include "lib-ansi.h"
 
-#define MAX_MODES 1
-struct commands_mode *list_modes[] = {
+struct cli_mode_descr *list_modes[] = {
+       &hdt_mode,
        &dmi_mode,
+       &syslinux_mode,
+       &pxe_mode,
+       &kernel_mode,
+       &cpu_mode,
+       &pci_mode,
+       &vesa_mode,
+       &vpd_mode,
+       NULL,
 };
 
-static void set_mode(struct s_cli *cli, cli_mode_t mode,
-                    struct s_hardware *hardware)
+/*
+ * .aliases = {"q", "quit"} won't work since it is an array of pointers, not an
+ * array of variables. There is no easy way around it besides declaring the arrays of
+ * strings first.
+ */
+char *exit_aliases[] = {"q", "quit"};
+char *help_aliases[] = {"h", "?"};
+
+/* List of aliases */
+struct cli_alias hdt_aliases[] = {
+       {
+               .command = CLI_EXIT,
+               .nb_aliases = 2,
+               .aliases = exit_aliases,
+       },
+       {
+               .command = CLI_HELP,
+               .nb_aliases = 2,
+               .aliases = help_aliases,
+       },
+};
+
+struct cli_mode_descr *current_mode;
+int autocomplete_backlog;
+
+struct autocomplete_list {
+       char autocomplete_token[MAX_LINE_SIZE];
+       struct autocomplete_list *next;
+};
+struct autocomplete_list* autocomplete_head = NULL;
+struct autocomplete_list* autocomplete_tail = NULL;
+struct autocomplete_list* autocomplete_last_seen = NULL;
+
+static void autocomplete_add_token_to_list(const char *token)
+{
+       struct autocomplete_list *new = malloc(sizeof(struct autocomplete_list));
+
+       strncpy(new->autocomplete_token, token, sizeof(new->autocomplete_token));
+       new->next = NULL;
+       autocomplete_backlog++;
+
+       if (autocomplete_tail != NULL)
+               autocomplete_tail->next = new;
+       if (autocomplete_head == NULL)
+               autocomplete_head = new;
+       autocomplete_tail = new;
+}
+
+static void autocomplete_destroy_list()
+{
+       struct autocomplete_list* tmp = NULL;
+
+       while (autocomplete_head != NULL) {
+               tmp = autocomplete_head->next;
+               free(autocomplete_head);
+               autocomplete_head = tmp;
+       }
+       autocomplete_backlog = 0;
+       autocomplete_tail = NULL;
+       autocomplete_last_seen = NULL;
+}
+
+/**
+ * set_mode - set the current mode of the cli
+ * @mode:      mode to set
+ *
+ * Unlike cli_set_mode, this function is not used by the cli directly.
+ **/
+void set_mode(cli_mode_t mode, struct s_hardware* hardware)
 {
+       int i = 0;
+
        switch (mode) {
        case EXIT_MODE:
-               cli->mode = mode;
+               hdt_cli.mode = mode;
                break;
-
        case HDT_MODE:
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_HDT);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_HDT);
                break;
-
        case PXE_MODE:
                if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) {
-                       more_printf("You are not currently using PXELINUX\n");
+                       printf("You are not currently using PXELINUX\n");
                        break;
                }
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_PXE);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_PXE);
                break;
-
        case KERNEL_MODE:
                detect_pci(hardware);
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_KERNEL);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_KERNEL);
                break;
-
        case SYSLINUX_MODE:
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ",
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
                         CLI_SYSLINUX);
                break;
-
        case VESA_MODE:
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_VESA);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_VESA);
                break;
-
        case PCI_MODE:
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_PCI);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_PCI);
                if (!hardware->pci_detection)
                        cli_detect_pci(hardware);
                break;
-
        case CPU_MODE:
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_CPU);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_CPU);
                if (!hardware->dmi_detection)
                        detect_dmi(hardware);
                if (!hardware->cpu_detection)
                        cpu_detect(hardware);
                break;
-
        case DMI_MODE:
                detect_dmi(hardware);
                if (!hardware->is_dmi_valid) {
-                       more_printf("No valid DMI table found, exiting.\n");
+                       printf("No valid DMI table found, exiting.\n");
                        break;
                }
-               cli->mode = mode;
-               snprintf(cli->prompt, sizeof(cli->prompt), "%s> ", CLI_DMI);
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_DMI);
                break;
+       case VPD_MODE:
+               detect_vpd(hardware);
+               if (!hardware->is_vpd_valid) {
+                       printf("No valid VPD table found, exiting.\n");
+                       break;
+               }
+               hdt_cli.mode = mode;
+               snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ",
+                        CLI_VPD);
+               break;
+
+       default:
+               /* Invalid mode */
+               printf("Unknown mode, please choose among:\n");
+               while (list_modes[i]) {
+                       printf("\t%s\n", list_modes[i]->name);
+                       i++;
+               }
+       }
+
+       find_cli_mode_descr(hdt_cli.mode, &current_mode);
+       /* 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);
        }
 }
 
-static void handle_hdt_commands(char *cli_line, struct s_hardware *hardware)
+/**
+ * mode_s_to_mode_t - given a mode string, return the cli_mode_t representation
+ **/
+cli_mode_t mode_s_to_mode_t(char *name)
 {
-       /* hdt cli mode specific commands */
-       if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-               main_show(strstr(cli_line, "show") + sizeof(CLI_SHOW),
-                         hardware);
-               return;
+       int i = 0;
+
+       while (list_modes[i]) {
+               if (!strncmp(name, list_modes[i]->name,
+                            sizeof(list_modes[i]->name)))
+                       break;
+               i++;
        }
+
+       if (!list_modes[i])
+               return INVALID_MODE;
+       else
+               return list_modes[i]->mode;
 }
 
-static void show_cli_help(struct s_cli *cli)
+/**
+ * find_cli_mode_descr - find the cli_mode_descr struct associated to a mode
+ * @mode:      mode to look for
+ * @mode_found:        store the mode if found, NULL otherwise
+ *
+ * Given a mode name, return a pointer to the associated cli_mode_descr
+ * structure.
+ * Note: the current mode name is stored in hdt_cli.mode.
+ **/
+void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found)
 {
-       switch (cli->mode) {
-       case HDT_MODE:
-               more_printf("Available commands are :\n");
-               more_printf
-                   ("%s %s %s %s %s %s %s %s %s %s %s\n",
-                    CLI_CLEAR, CLI_EXIT, CLI_HELP, CLI_SHOW, CLI_PCI, CLI_DMI,
-                    CLI_PXE, CLI_KERNEL, CLI_CPU, CLI_SYSLINUX, CLI_VESA);
-               break;
-       case SYSLINUX_MODE:
-       case KERNEL_MODE:
-       case PXE_MODE:
-       case VESA_MODE:
-       case CPU_MODE:
-       case PCI_MODE:
-       case DMI_MODE:
-               printf("Available commands are : %s %s %s %s\n",
-                      CLI_CLEAR, CLI_EXIT, CLI_HELP, CLI_SHOW);
-               break;
-       case EXIT_MODE: /* Should not happen */
-               break;
+       int i = 0;
+
+       while (list_modes[i] &&
+              list_modes[i]->mode != mode)
+               i++;
+
+       /* Shouldn't get here... */
+       if (!list_modes[i])
+               *mode_found = NULL;
+       else
+               *mode_found = list_modes[i];
+}
+
+/**
+ * expand_aliases - resolve aliases mapping
+ * @line:      command line to parse
+ * @command:   first token in the line
+ * @module:    second token in the line
+ * @argc:      number of arguments
+ * @argv:      array of arguments
+ *
+ * We maintain a small list of static alises to enhance user experience.
+ * Only commands can be aliased (first token). Otherwise it can become really hairy...
+ **/
+static void expand_aliases(char *line __unused, char **command, char **module,
+                          int *argc, char **argv)
+{
+       struct cli_mode_descr *mode;
+       int i, j;
+
+       find_cli_mode_descr(mode_s_to_mode_t(*command), &mode);
+       if (mode != NULL && *module == NULL) {
+               /*
+                * The user specified a mode instead of `set mode...', e.g.
+                * `dmi' instead of `set mode dmi'
+                */
+
+               /* *argv is NULL since *module is NULL */
+               *argc = 1;
+               *argv = malloc(*argc * sizeof(char *));
+               argv[0] = malloc((sizeof(*command) + 1) * sizeof(char));
+               strncpy(argv[0], *command, sizeof(*command) + 1);
+               dprintf("CLI DEBUG: ALIAS %s ", *command);
+
+               strncpy(*command, CLI_SET, sizeof(CLI_SET));    /* set */
+
+               *module = malloc(sizeof(CLI_MODE) * sizeof(char));
+               strncpy(*module, CLI_MODE, sizeof(CLI_MODE));   /* mode */
+
+               dprintf("--> %s %s %s\n", *command, *module, argv[0]);
+               goto out;
+       }
+
+       /* Simple aliases mapping a single command to another one */
+       for (i = 0; i < MAX_ALIASES; i++) {
+               for (j = 0; j < hdt_aliases[i].nb_aliases; j++) {
+                       if (!strncmp(*command, hdt_aliases[i].aliases[j],
+                           sizeof(hdt_aliases[i].aliases[j]))) {
+                               dprintf("CLI DEBUG: ALIAS %s ", *command);
+                               strncpy(*command, hdt_aliases[i].command,
+                                       sizeof(hdt_aliases[i].command) + 1);
+                               dprintf("--> %s\n", *command);
+                               goto out; /* Don't allow chaining aliases */
+                       }
+               }
        }
+       return;
+
+out:
+       dprintf("CLI DEBUG: New parameters:\n");
+       dprintf("CLI DEBUG: command = %s\n", *command);
+       dprintf("CLI DEBUG: module  = %s\n", *module);
+       dprintf("CLI DEBUG: argc    = %d\n", *argc);
+       for (i = 0; i < *argc; i++)
+               dprintf("CLI DEBUG: argv[%d] = %s\n", i, argv[0]);
+       return;
 }
 
-static void exec_command(char *command, struct s_cli *cli,
-                        struct s_hardware *hardware)
+/**
+ * parse_command_line - low level parser for the command line
+ * @line:      command line to parse
+ * @command:   first token in the line
+ * @module:    second token in the line
+ * @argc:      number of arguments
+ * @argv:      array of arguments
+ *
+ * The format of the command line is:
+ *     <main command> [<module on which to operate> [<args>]]
+ **/
+static void parse_command_line(char *line, char **command, char **module,
+                              int *argc, char **argv)
 {
-       /* We use sizeof BLAH - 1 to remove the last \0 */
-//  command[strlen(command) - 1] = '\0';
+       int argc_iter = 0, args_pos = 0, token_found = 0, token_len = 0;
+       int args_len = 0;
+       char *pch = NULL, *pch_next = NULL, *tmp_pch_next = NULL;
 
-       if (!strncmp(command, CLI_EXIT, sizeof(CLI_EXIT) - 1)) {
-               int mode = do_exit(cli);
-               set_mode(cli, mode, hardware);
-               return;
+       *command = NULL;
+       *module = NULL;
+       *argc = 0;
+
+       pch = line;
+       while (pch != NULL) {
+               pch_next = strchr(pch + 1, ' ');
+               tmp_pch_next = pch_next;
+
+               /*
+                * Skip whitespaces if the user entered
+                * 'set   mode        foo' for 'set mode foo'
+                *  ^   ^
+                *  |___|___ pch
+                *      |___ pch_next <- wrong!
+                *
+                *  We still keep the position into tmp_pch_next to compute
+                *  the lenght of the current token.
+                */
+               while (pch_next != NULL && !strncmp(pch_next, CLI_SPACE, 1))
+                       pch_next++;
+
+               /* End of line guaranteed to be zeroed */
+               if (pch_next == NULL) {
+                       token_len = (int) (strchr(pch + 1, '\0') - pch);
+                       args_len = token_len;
+               }
+               else {
+                       token_len = (int) (tmp_pch_next - pch);
+                       args_len = (int) (pch_next - pch);
+               }
+
+               if (token_found == 0) {
+                       /* Main command to execute */
+                       *command = malloc((token_len + 1) * sizeof(char));
+                       strncpy(*command, pch, token_len);
+                       (*command)[token_len] = '\0';
+                       dprintf("CLI DEBUG: command = %s\n", *command);
+                       args_pos += args_len;
+               } else if (token_found == 1) {
+                       /* Module */
+                       *module = malloc((token_len + 1) * sizeof(char));
+                       strncpy(*module, pch, token_len);
+                       (*module)[token_len] = '\0';
+                       dprintf("CLI DEBUG: module  = %s\n", *module);
+                       args_pos += args_len;
+               } else
+                       (*argc)++;
+
+               token_found++;
+               pch = pch_next;
        }
+       dprintf("CLI DEBUG: argc    = %d\n", *argc);
 
-       if (!strncmp(command, CLI_HELP, sizeof(CLI_HELP) - 1)) {
-               show_cli_help(cli);
+       /* Skip arguments handling if none is supplied */
+       if (!*argc)
                return;
+
+       /* Transform the arguments string into an array */
+       *argv = malloc(*argc * sizeof(char *));
+       pch = strtok(line + args_pos, CLI_SPACE);
+       while (pch != NULL) {
+               dprintf("CLI DEBUG: argv[%d] = %s\n", argc_iter, pch);
+               argv[argc_iter] = malloc(sizeof(pch) * sizeof(char));
+               strncpy(argv[argc_iter], pch, sizeof(pch));
+               argc_iter++;
+               pch = strtok(NULL, CLI_SPACE);
+               /*
+                * strtok(NULL, CLI_SPACE) over a stream of spaces
+                * will return an empty string
+                */
+               while (pch != NULL && !strncmp(pch, "", 1))
+                       pch = strtok(NULL, CLI_SPACE);
        }
+}
 
-       if (!strncmp(command, CLI_PCI, sizeof(CLI_PCI) - 1)) {
-               set_mode(cli, PCI_MODE, hardware);
+/**
+ * find_cli_callback_descr - find a callback in a list of modules
+ * @module_name:       Name of the module to find
+ * @modules_list:      Lits of modules among which to find @module_name
+ * @module_found:      Pointer to the matched module, NULL if not found
+ *
+ * Given a module name and a list of possible modules, find the corresponding
+ * module structure that matches the module name and store it in @module_found.
+ **/
+void find_cli_callback_descr(const char* module_name,
+                            struct cli_module_descr* modules_list,
+                            struct cli_callback_descr** module_found)
+{
+       int modules_iter = 0;
+       int module_len = strlen(module_name);
+
+       if (modules_list == NULL)
+               goto not_found;
+
+       /* Find the callback to execute */
+       while (modules_list->modules[modules_iter].name &&
+              strncmp(module_name,
+                      modules_list->modules[modules_iter].name,
+                      module_len) != 0)
+               modules_iter++;
+
+       if (modules_list->modules[modules_iter].name) {
+               *module_found = &(modules_list->modules[modules_iter]);
+               dprintf("CLI DEBUG: module %s found\n", (*module_found)->name);
                return;
        }
 
-       if (!strncmp(command, CLI_CLEAR, sizeof(CLI_CLEAR) - 1)) {
-               clear_screen();
-               return;
+not_found:
+       *module_found = NULL;
+       return;
+}
+
+/**
+ * autocomplete_command - print matching commands
+ * @command:   Beginning of the command
+ *
+ * Given a string @command, print all availables commands starting with
+ * @command. Commands are found within the list of commands for the current
+ * mode and the hdt mode (if the current mode is not hdt).
+ **/
+static void autocomplete_command(char *command)
+{
+       int j = 0;
+       struct cli_callback_descr* associated_module = NULL;
+
+       /* First take care of the two special commands: 'show' and 'set' */
+       if (strncmp(CLI_SHOW, command, strlen(command)) == 0) {
+               printf("%s\n", CLI_SHOW);
+               autocomplete_add_token_to_list(CLI_SHOW);
+       }
+       if (strncmp(CLI_SET, command, strlen(command)) == 0) {
+               printf("%s\n", CLI_SET);
+               autocomplete_add_token_to_list(CLI_SET);
        }
 
-       if (!strncmp(command, CLI_CPU, sizeof(CLI_CPU) - 1)) {
-               set_mode(cli, CPU_MODE, hardware);
-               return;
+       /*
+        * Then, go through the modes for the special case
+        *      '<mode>' -> 'set mode <mode>'
+        */
+       while (list_modes[j]) {
+               if (strncmp(list_modes[j]->name, command, strlen(command)) == 0) {
+                       printf("%s\n", list_modes[j]->name);
+                       autocomplete_add_token_to_list(list_modes[j]->name);
+               }
+               j++;
        }
 
-       if (!strncmp(command, CLI_DMI, sizeof(CLI_DMI) - 1)) {
-               set_mode(cli, DMI_MODE, hardware);
-               return;
+       /*
+        * Let's go now through the list of default_modules for the current mode
+        * (single token commands for the current_mode)
+        */
+       j = 0;
+       while (current_mode->default_modules->modules[j].name) {
+               if (strncmp(current_mode->default_modules->modules[j].name,
+                           command,
+                           strlen(command)) == 0) {
+                       printf("%s\n",
+                               current_mode->default_modules->modules[j].name);
+                       autocomplete_add_token_to_list(current_mode->default_modules->modules[j].name);
+               }
+               j++;
        }
 
-       if (!strncmp(command, CLI_PXE, sizeof(CLI_PXE) - 1)) {
-               set_mode(cli, PXE_MODE, hardware);
+       /*
+        * Finally, if the current_mode is not hdt, list the available
+        * default_modules of hdt (these are always available from any mode).
+        */
+       if (current_mode->mode == HDT_MODE)
                return;
+
+       j = 0;
+       while (hdt_mode.default_modules->modules[j].name) {
+               /*
+                * Any default command that is present in hdt mode but
+                * not in the current mode is available. A default
+                * command can be redefined in the current mode though.
+                * This next call tests this use case: if it is
+                * overwritten, do not print it again.
+                */
+               find_cli_callback_descr(hdt_mode.default_modules->modules[j].name,
+                                       current_mode->default_modules,
+                                       &associated_module);
+               if (associated_module == NULL &&
+                   strncmp(command,
+                           hdt_mode.default_modules->modules[j].name,
+                           strlen(command)) == 0) {
+                       printf("%s\n",
+                               hdt_mode.default_modules->modules[j].name);
+                       autocomplete_add_token_to_list(hdt_mode.default_modules->modules[j].name);
+               }
+               j++;
        }
+}
 
-       if (!strncmp(command, CLI_KERNEL, sizeof(CLI_KERNEL) - 1)) {
-               set_mode(cli, KERNEL_MODE, hardware);
-               return;
+/**
+ * autocomplete_module - print matching modules
+ * @command:   Command on the command line (not NULL)
+ * @module:    Beginning of the module
+ *
+ * Given a command @command and a string @module, print all availables modules
+ * starting with @module for command @command. Commands are found within the
+ * list of commands for the current mode and the hdt mode (if the current mode
+ * is not hdt).
+ **/
+static void autocomplete_module(char *command, char* module)
+{
+       int j = 0;
+       char autocomplete_full_line[MAX_LINE_SIZE];
+
+       if (strncmp(CLI_SHOW, command, strlen(command)) == 0) {
+               while (current_mode->show_modules->modules[j].name) {
+                       if (strncmp(current_mode->show_modules->modules[j].name,
+                                   module,
+                                   strlen(module)) == 0) {
+                               printf("%s\n",
+                                       current_mode->show_modules->modules[j].name);
+                               sprintf(autocomplete_full_line, "%s %s",
+                                       CLI_SHOW, current_mode->show_modules->modules[j].name);
+                               autocomplete_add_token_to_list(autocomplete_full_line);
+                       }
+               j++;
+               }
+       } else if (strncmp(CLI_SET, command, strlen(command)) == 0) {
+               j = 0;
+               while (current_mode->set_modules->modules[j].name) {
+                       if (strncmp(current_mode->set_modules->modules[j].name,
+                                   module,
+                                   strlen(module)) == 0) {
+                               printf("%s\n",
+                                       current_mode->set_modules->modules[j].name);
+                               sprintf(autocomplete_full_line, "%s %s",
+                                       CLI_SET, current_mode->set_modules->modules[j].name);
+                               autocomplete_add_token_to_list(autocomplete_full_line);
+                       }
+                       j++;
+               }
        }
+}
 
-       if (!strncmp(command, CLI_SYSLINUX, sizeof(CLI_SYSLINUX) - 1)) {
-               set_mode(cli, SYSLINUX_MODE, hardware);
-               return;
+/**
+ * autocomplete - find possible matches for a command line
+ * @line:      command line to parse
+ **/
+static void autocomplete(char *line)
+{
+       int i;
+       int argc = 0;
+       char *command = NULL, *module = NULL;
+       char **argv = NULL;
+
+       parse_command_line(line, &command, &module, &argc, argv);
+
+       /* If the user specified arguments, there is nothing we can complete */
+       if (argc != 0)
+               goto out;
+
+       /* No argument, (the start of) a module has been specified */
+       if (module != NULL) {
+               autocomplete_module(command, module);
+               goto out;
        }
 
-       if (!strncmp(command, CLI_VESA, sizeof(CLI_VESA) - 1)) {
-               set_mode(cli, VESA_MODE, hardware);
-               return;
+       /* No argument, no module, (the start of) a command has been specified */
+       if (command != NULL) {
+               autocomplete_command(command);
+               goto out;
        }
 
-       /*
-        * All commands before that line are common for all cli modes.
-        * The following will be specific for every mode.
-        */
+       /* Nothing specified, list available commands */
+       //autocomplete_commands();
+
+out:
+       /* Let's not forget to clean ourselves */
+       free(command);
+       free(module);
+       for (i = 0; i < argc; i++)
+               free(argv[i]);
+       free(argv);
+       return;
+}
 
-       int modes_iter = 0, modules_iter = 0;
 
-       /* Find the mode selected */
-       while (modes_iter < MAX_MODES &&
-              list_modes[modes_iter]->mode != cli->mode)
-               modes_iter++;
+/**
+ * exec_command - main logic to map the command line to callbacks
+ **/
+static void exec_command(char *line,
+                        struct s_hardware *hardware)
+{
+       int argc, i = 0;
+       char *command = NULL, *module = NULL;
+       char **argv = NULL;
+       struct cli_callback_descr* current_module = NULL;
 
-       if (modes_iter != MAX_MODES) {
-               struct commands_mode *current_mode = list_modes[modes_iter];
+       /* This will allocate memory that will need to be freed */
+       parse_command_line(line, &command, &module, &argc, argv);
 
+       /* Expand shortcuts, if needed */
+       expand_aliases(line, &command, &module, &argc, argv);
+
+       if (module == NULL) {
+               dprintf("CLI DEBUG: single command detected\n", CLI_SHOW);
                /*
-                * Find the type of command.
-                *
-                * The syntax of the cli is the following:
-                *    <type of command> <module on which to operate> <args>
-                * e.g.
-                *    dmi> show system
-                *    dmi> show bank 1
-                *    dmi> show memory 0 1
-                *    pci> show device 12
+                * A single word was specified: look at the list of default
+                * commands in the current mode to see if there is a match.
+                * If not, it may be a generic function (exit, help, ...). These
+                * are stored in the list of default commands of the hdt mode.
                 */
-               if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-                       int module_len = 0, args_len = 0;
-                       int argc = 0, args_iter = 0, argc_iter = 0;
-                       char *module = NULL, *args = NULL, *args_cpy = NULL;
-                       char **argv = NULL;
-
-                       /* Get the module name and args */
-                       while (strncmp
-                              (command + sizeof(CLI_SHOW) + module_len,
-                               CLI_SPACE, 1))
-                               module_len++;
-
-                       /* cli_line is filled with \0 when initialized */
-                       while (strncmp
-                              (command + sizeof(CLI_SHOW) + module_len + 1 +
-                               args_len, "\0", 1))
-                               args_len++;
-
-                       module = malloc(module_len + 1);
-                       strncpy(module, command + sizeof(CLI_SHOW), module_len);
-                       module[module_len] = '\0';
-
-                       /* Skip arguments handling if none is supplied */
-                       if (!args_len)
-                               goto find_callback;
-
-                       args = malloc(args_len + 1);
-                       strncpy(args,
-                               command + sizeof(CLI_SHOW) + module_len + 1,
-                               args_len);
-                       args[args_len] = '\0';
-
-                       /* Compute the number of arguments */
-                       args_cpy = args;
- read_argument:
-                       args_iter = 0;
-                       while (args_iter < args_len
-                              && strncmp(args_cpy + args_iter, CLI_SPACE, 1))
-                               args_iter++;
-                       argc++;
-                       args_iter++;
-                       args_cpy += args_iter;
-                       args_len -= args_iter;
-                       if (args_len > 0)
-                               goto read_argument;
-
-                       /* Transform the arguments string into an array */
-                       char *result = NULL;
-                       argv = malloc(argc * sizeof(char *));
-                       result = strtok(args, CLI_SPACE);
-                       while (result != NULL) {
-                               argv[argc_iter] = result;
-                               argc_iter++;
-                               result = strtok(NULL, CLI_SPACE);
-                       }
+               find_cli_callback_descr(command, current_mode->default_modules,
+                                       &current_module);
+               if (current_module != NULL)
+                       return current_module->exec(argc, argv, hardware);
+               else if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1) &&
+                        current_mode->show_modules != NULL &&
+                        current_mode->show_modules->default_callback != NULL)
+                       return current_mode->show_modules
+                                          ->default_callback(argc,
+                                                             argv,
+                                                             hardware);
+               else if (!strncmp(command, CLI_SET, sizeof(CLI_SET) - 1) &&
+                        current_mode->set_modules != NULL &&
+                        current_mode->set_modules->default_callback != NULL)
+                       return current_mode->set_modules
+                                          ->default_callback(argc,
+                                                             argv,
+                                                             hardware);
+               else {
+                       find_cli_callback_descr(command, hdt_mode.default_modules,
+                                               &current_module);
+                       if (current_module != NULL)
+                               return current_module->exec(argc, argv, hardware);
+               }
 
- find_callback:
-                       /* Find the callback to execute */
-                       while (modules_iter <
-                              current_mode->show_modules->nb_modules
-                              && strncmp(module,
-                                         current_mode->show_modules->
-                                         modules[modules_iter].name,
-                                         module_len + 1) != 0)
-                               modules_iter++;
-
-                       if (modules_iter !=
-                           current_mode->show_modules->nb_modules) {
-                               struct commands_module current_module =
-                                   current_mode->show_modules->
-                                   modules[modules_iter];
-                               /* Execute the callback */
-                               current_module.exec(argc, argv, hardware);
-                       } else
-//                             printf("Module %s unknown.\n", module);
-                       /* XXX Add a default help option for empty commands */
-
-                       free(module);
-                       if (args_len) {
-                               free(args);
-                               free(argv);
-                       }
+               printf("unknown command: '%s'\n", command);
+               return;
+       }
+
+       /*
+        * A module has been specified! We now need to find the type of command.
+        *
+        * The syntax of the cli is the following:
+        *    <type of command> <module on which to operate> <args>
+        * e.g.
+        *    dmi> show system
+        *    dmi> show bank 1
+        *    dmi> show memory 0 1
+        *    pci> show device 12
+        *    hdt> set mode dmi
+        */
+       if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
+               dprintf("CLI DEBUG: %s command detected\n", CLI_SHOW);
+               find_cli_callback_descr(module, current_mode->show_modules,
+                                       &current_module);
+               /* Execute the callback */
+               if (current_module != NULL)
+                       return current_module->exec(argc, argv, hardware);
+               else {
+                       find_cli_callback_descr(module, hdt_mode.show_modules,
+                                               &current_module);
+                       if (current_module != NULL)
+                               return current_module->exec(argc, argv, hardware);
                }
-               /* Handle here other keywords such as 'set', ... */
-       } else
-//             printf("Mode '%s' unknown.\n", command);
 
-       /* Legacy cli */
-       switch (cli->mode) {
-       case PCI_MODE:
-               handle_pci_commands(command, hardware);
-               break;
-       case HDT_MODE:
-               handle_hdt_commands(command, hardware);
-               break;
-       case CPU_MODE:
-               handle_cpu_commands(command, hardware);
-               break;
-       case PXE_MODE:
-               handle_pxe_commands(command, hardware);
-               break;
-       case VESA_MODE:
-               handle_vesa_commands(command, hardware);
-               break;
-       case SYSLINUX_MODE:
-               handle_syslinux_commands(command, hardware);
-               break;
-       case KERNEL_MODE:
-               handle_kernel_commands(command, hardware);
-               break;
-       case EXIT_MODE:
-               break;          /* should not happen */
+               printf("unknown module: '%s'\n", module);
+               return;
+
+       } else if (!strncmp(command, CLI_SET, sizeof(CLI_SET) - 1)) {
+               dprintf("CLI DEBUG: %s command detected\n", CLI_SET);
+               find_cli_callback_descr(module, current_mode->set_modules,
+                                       &current_module);
+               /* Execute the callback */
+               if (current_module != NULL)
+                       return current_module->exec(argc, argv, hardware);
+               else {
+                       find_cli_callback_descr(module, hdt_mode.set_modules,
+                                               &current_module);
+                       if (current_module != NULL)
+                               return current_module->exec(argc, argv, hardware);
+               }
+
+               printf("unknown module: '%s'\n", module);
+               return;
+
        }
+
+       printf("I don't understand: '%s'. Try 'help'.\n", line);
+
+       /* Let's not forget to clean ourselves */
+       free(command);
+       free(module);
+       for (i = 0; i < argc; i++)
+               free(argv[i]);
+       free(argv);
 }
 
-static void reset_prompt(struct s_cli *cli)
+static void reset_prompt()
 {
        /* No need to display the prompt if we exit */
-       if (cli->mode != EXIT_MODE) {
-               printf("%s", cli->prompt);
+       if (hdt_cli.mode != EXIT_MODE) {
+               printf("%s", hdt_cli.prompt);
                /* Reset the line */
-               memset(cli->input, '\0', MAX_LINE_SIZE);
-               cli->cursor_pos = 0;
+               memset(hdt_cli.input, '\0', MAX_LINE_SIZE);
+               hdt_cli.cursor_pos = 0;
        }
 }
 
@@ -357,55 +748,62 @@ void start_cli_mode(struct s_hardware *hardware)
        bool display_history=true; /* Temp Variable*/
        char temp_command[MAX_LINE_SIZE];
 
-       struct s_cli cli;
-       cli.cursor_pos=0;
-       memset(cli.input, '\0', MAX_LINE_SIZE);
-       memset(cli.history, '\0', sizeof(cli.history));
-       cli.history_pos=1;
-       cli.max_history_pos=1;
+       hdt_cli.cursor_pos=0;
+       memset(hdt_cli.input, '\0', MAX_LINE_SIZE);
+       memset(hdt_cli.history, '\0', sizeof(hdt_cli.history));
+       hdt_cli.history_pos=1;
+       hdt_cli.max_history_pos=1;
 
-       set_mode(&cli, HDT_MODE, hardware);
+       /* Find the mode selected */
+       set_mode(HDT_MODE, hardware);
+       find_cli_mode_descr(hdt_cli.mode, &current_mode);
+       if (current_mode == NULL) {
+               /* Shouldn't get here... */
+               printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode);
+               return;
+       }
 
        printf("Entering CLI mode\n");
 
        /* Display the cursor */
-       fputs("\033[?25h", stdout);
+       display_cursor(true);
 
-       reset_prompt(&cli);
+       reset_prompt();
 
-       while (cli.mode != EXIT_MODE) {
+       while (hdt_cli.mode != EXIT_MODE) {
 
                //fgets(cli_line, sizeof cli_line, stdin);
                current_key = get_key(stdin, 0);
 
+               /* Reset autocomplete buffer unless TAB is pressed */
+               if (current_key != KEY_TAB)
+                       autocomplete_destroy_list();
+
                switch (current_key) {
                        /* clear until then end of line */
                case KEY_CTRL('k'):
                        /* Clear the end of the line */
-                       fputs("\033[0K", stdout);
-                       memset(&cli.input[cli.cursor_pos], 0,
-                              strlen(cli.input) - cli.cursor_pos);
+                       clear_end_of_line();
+                       memset(&hdt_cli.input[hdt_cli.cursor_pos], 0,
+                              strlen(hdt_cli.input) - hdt_cli.cursor_pos);
                        break;
 
                case KEY_CTRL('c'):
-                       more_printf("\n");
-                       reset_prompt(&cli);
-                       break;
-
-               case KEY_TAB:
+                       printf("\n");
+                       reset_prompt();
                        break;
 
                case KEY_LEFT:
-                       if (cli.cursor_pos > 0) {
-                               fputs("\033[1D", stdout);
-                               cli.cursor_pos--;
+                       if (hdt_cli.cursor_pos > 0) {
+                               move_cursor_left(1);
+                               hdt_cli.cursor_pos--;
                        }
                        break;
 
                case KEY_RIGHT:
-                       if (cli.cursor_pos < (int)strlen(cli.input)) {
-                               fputs("\033[1C", stdout);
-                               cli.cursor_pos++;
+                       if (hdt_cli.cursor_pos < (int)strlen(hdt_cli.input)) {
+                               move_cursor_right(1);
+                               hdt_cli.cursor_pos++;
                        }
                        break;
 
@@ -413,13 +811,10 @@ void start_cli_mode(struct s_hardware *hardware)
                case KEY_END:
                        /* Calling with a 0 value will make the cursor move */
                        /* So, let's move the cursor only if needed */
-                       if ((strlen(cli.input) - cli.cursor_pos) > 0) {
-                               memset(temp_command, 0, sizeof(temp_command));
-                               sprintf(temp_command, "\033[%dC",
-                                       strlen(cli.input) - cli.cursor_pos);
+                       if ((strlen(hdt_cli.input) - hdt_cli.cursor_pos) > 0) {
                                /* Return to the begining of line */
-                               fputs(temp_command, stdout);
-                               cli.cursor_pos = strlen(cli.input);
+                               move_cursor_right(strlen(hdt_cli.input) - hdt_cli.cursor_pos);
+                               hdt_cli.cursor_pos = strlen(hdt_cli.input);
                        }
                        break;
 
@@ -427,290 +822,204 @@ void start_cli_mode(struct s_hardware *hardware)
                case KEY_HOME:
                        /* Calling with a 0 value will make the cursor move */
                        /* So, let's move the cursor only if needed */
-                       if (cli.cursor_pos > 0) {
-                               memset(temp_command, 0, sizeof(temp_command));
-                               sprintf(temp_command, "\033[%dD",
-                                       cli.cursor_pos);
+                       if (hdt_cli.cursor_pos > 0) {
                                /* Return to the begining of line */
-                               fputs(temp_command, stdout);
-                               cli.cursor_pos = 0;
+                               move_cursor_left(hdt_cli.cursor_pos);
+                               hdt_cli.cursor_pos = 0;
                        }
                        break;
 
                case KEY_UP:
                        /* We have to compute the next position*/
-                       future_history_pos=cli.history_pos;
+                       future_history_pos=hdt_cli.history_pos;
                        if (future_history_pos==1) {
                                future_history_pos=MAX_HISTORY_SIZE-1;
                        } else {
                                future_history_pos--;
                        }
                        /* Does the next position is valid */
-                       if (strlen(cli.history[future_history_pos])==0) break;
+                       if (strlen(hdt_cli.history[future_history_pos])==0) break;
 
                        /* Let's make that future position the one we use*/
-                       cli.history_pos=future_history_pos;
+                       hdt_cli.history_pos=future_history_pos;
 
                        /* Clear the line */
-                       fputs("\033[2K", stdout);
+                       clear_line();
 
                        /* Move to the begining of line*/
-                       fputs("\033[0G", stdout);
+                       move_cursor_to_column(0);
 
-                       reset_prompt(&cli);
-                       printf("%s",cli.history[cli.history_pos]);
-                       strncpy(cli.input,cli.history[cli.history_pos],sizeof(cli.input));
-                       cli.cursor_pos=strlen(cli.input);
+                       reset_prompt();
+                       printf("%s",hdt_cli.history[hdt_cli.history_pos]);
+                       strncpy(hdt_cli.input,hdt_cli.history[hdt_cli.history_pos],sizeof(hdt_cli.input));
+                       hdt_cli.cursor_pos=strlen(hdt_cli.input);
                        break;
 
                case KEY_DOWN:
                        display_history=true;
 
                        /* We have to compute the next position*/
-                       future_history_pos=cli.history_pos;
+                       future_history_pos=hdt_cli.history_pos;
                        if (future_history_pos==MAX_HISTORY_SIZE-1) {
                                future_history_pos=1;
                        } else {
                                future_history_pos++;
                        }
                        /* Does the next position is valid */
-                       if (strlen(cli.history[future_history_pos])==0) display_history = false;
+                       if (strlen(hdt_cli.history[future_history_pos])==0) display_history = false;
 
                        /* An exception is made to reach the last empty line */
-                       if (future_history_pos==cli.max_history_pos) display_history=true;
+                       if (future_history_pos==hdt_cli.max_history_pos) display_history=true;
                        if (display_history==false) break;
 
                        /* Let's make that future position the one we use*/
-                       cli.history_pos=future_history_pos;
+                       hdt_cli.history_pos=future_history_pos;
 
                        /* Clear the line */
-                       fputs("\033[2K", stdout);
+                       clear_line();
 
                        /* Move to the begining of line*/
-                       fputs("\033[0G", stdout);
+                       move_cursor_to_column(0);
 
-                       reset_prompt(&cli);
-                       printf("%s",cli.history[cli.history_pos]);
-                       strncpy(cli.input,cli.history[cli.history_pos],sizeof(cli.input));
-                       cli.cursor_pos=strlen(cli.input);
+                       reset_prompt();
+                       printf("%s",hdt_cli.history[hdt_cli.history_pos]);
+                       strncpy(hdt_cli.input,hdt_cli.history[hdt_cli.history_pos],sizeof(hdt_cli.input));
+                       hdt_cli.cursor_pos=strlen(hdt_cli.input);
                        break;
 
-               case KEY_ENTER:
-                       more_printf("\n");
+               case KEY_TAB:
+                       if (autocomplete_backlog) {
+                               clear_line();
+                               /* Move to the begining of line*/
+                               move_cursor_to_column(0);
+                               reset_prompt();
+                               printf("%s",autocomplete_last_seen->autocomplete_token);
+                               strncpy(hdt_cli.input,autocomplete_last_seen->autocomplete_token,sizeof(hdt_cli.input));
+                               hdt_cli.cursor_pos=strlen(hdt_cli.input);
+
+                               /* Cycle through the list */
+                               autocomplete_last_seen = autocomplete_last_seen->next;
+                               if (autocomplete_last_seen == NULL)
+                                       autocomplete_last_seen = autocomplete_head;
+                       } else {
+                               printf("\n");
+                               autocomplete(skip_spaces(hdt_cli.input));
+                               autocomplete_last_seen = autocomplete_head;
+
+                               printf("%s%s", hdt_cli.prompt, hdt_cli.input);
+                       }
+                       break;
 
-                       /* We have to skip empty lines */
-                       if (strlen(skipspace(cli.input))<1) {
-                               reset_prompt(&cli);
+               case KEY_ENTER:
+                       printf("\n");
+                       if (strlen(remove_spaces(hdt_cli.input)) < 1) {
+                               reset_prompt();
                                break;
                        }
-                       if (cli.history_pos == MAX_HISTORY_SIZE-1) cli.history_pos=1;
-                       strncpy(cli.history[cli.history_pos],skipspace(cli.input),sizeof(cli.history[cli.history_pos]));
-                       cli.history_pos++;
-                       if (cli.history_pos>cli.max_history_pos) cli.max_history_pos=cli.history_pos;
-                       exec_command(skipspace(cli.input), &cli, hardware);
-                       reset_prompt(&cli);
+                       if (hdt_cli.history_pos == MAX_HISTORY_SIZE-1) hdt_cli.history_pos=1;
+                       strncpy(hdt_cli.history[hdt_cli.history_pos],remove_spaces(hdt_cli.input),sizeof(hdt_cli.history[hdt_cli.history_pos]));
+                       hdt_cli.history_pos++;
+                       if (hdt_cli.history_pos>hdt_cli.max_history_pos) hdt_cli.max_history_pos=hdt_cli.history_pos;
+                       exec_command(remove_spaces(hdt_cli.input), hardware);
+                       reset_prompt();
                        break;
 
+               case KEY_CTRL('d'):
+                case KEY_DELETE:
+                        /* No need to delete when input is empty */
+                        if (strlen(hdt_cli.input)==0) break;
+                        /* Don't delete when cursor is at the end of the line */
+                        if (hdt_cli.cursor_pos>=strlen(hdt_cli.input)) break;
+
+                       for (int c = hdt_cli.cursor_pos;
+                            c < (int)strlen(hdt_cli.input) - 1; c++)
+                               hdt_cli.input[c] = hdt_cli.input[c + 1];
+                       hdt_cli.input[strlen(hdt_cli.input) - 1] = '\0';
+
+                       /* Clear the end of the line */
+                       clear_end_of_line();
+
+                       /* Print the resulting buffer */
+                       printf("%s", hdt_cli.input + hdt_cli.cursor_pos);
+
+                       /* Replace the cursor at the proper place */
+                       if (strlen(hdt_cli.input + hdt_cli.cursor_pos)>0)
+                               move_cursor_left(strlen(hdt_cli.input + hdt_cli.cursor_pos));
+                       break;
+
+               case KEY_DEL:
                case KEY_BACKSPACE:
                        /* Don't delete prompt */
-                       if (cli.cursor_pos == 0)
+                       if (hdt_cli.cursor_pos == 0)
                                break;
 
-                       for (int c = cli.cursor_pos - 1;
-                            c < (int)strlen(cli.input) - 1; c++)
-                               cli.input[c] = cli.input[c + 1];
-                       cli.input[strlen(cli.input) - 1] = '\0';
+                       for (int c = hdt_cli.cursor_pos - 1;
+                            c < (int)strlen(hdt_cli.input) - 1; c++)
+                               hdt_cli.input[c] = hdt_cli.input[c + 1];
+                       hdt_cli.input[strlen(hdt_cli.input) - 1] = '\0';
 
                        /* Get one char back */
-                       fputs("\033[1D", stdout);
+                       move_cursor_left(1);
+
                        /* Clear the end of the line */
-                       fputs("\033[0K", stdout);
+                       clear_end_of_line();
 
                        /* Print the resulting buffer */
-                       printf("%s", cli.input + cli.cursor_pos - 1);
+                       printf("%s", hdt_cli.input + hdt_cli.cursor_pos - 1);
 
                        /* Realing to the place we were */
-                       memset(temp_command, 0, sizeof(temp_command));
-                       sprintf(temp_command, "\033[%dD",
-                               strlen(cli.input + cli.cursor_pos - 1));
-                       fputs(temp_command, stdout);
-                       fputs("\033[1C", stdout);
+                       move_cursor_left(strlen(hdt_cli.input + hdt_cli.cursor_pos - 1));
+                       move_cursor_right(1);
+
                        /* Don't decrement the position unless
                         * if we are at then end of the line*/
-                       if (cli.cursor_pos > (int)strlen(cli.input))
-                               cli.cursor_pos--;
+                       if (hdt_cli.cursor_pos > (int)strlen(hdt_cli.input))
+                               hdt_cli.cursor_pos--;
                        break;
 
                case KEY_F1:
-                       more_printf("\n");
-                       exec_command(CLI_HELP, &cli, hardware);
-                       reset_prompt(&cli);
+                       printf("\n");
+                       exec_command(CLI_HELP, hardware);
+                       reset_prompt();
                        break;
 
                default:
                        if ( ( current_key < 0x20 ) || ( current_key > 0x7e ) ) break;
                        /* Prevent overflow */
-                       if (cli.cursor_pos > MAX_LINE_SIZE - 2)
+                       if (hdt_cli.cursor_pos > MAX_LINE_SIZE - 2)
                                break;
                        /* If we aren't at the end of the input line, let's insert */
-                       if (cli.cursor_pos < (int)strlen(cli.input)) {
+                       if (hdt_cli.cursor_pos < (int)strlen(hdt_cli.input)) {
                                char key[2];
                                int trailing_chars =
-                                   strlen(cli.input) - cli.cursor_pos;
+                                   strlen(hdt_cli.input) - hdt_cli.cursor_pos;
                                memset(temp_command, 0, sizeof(temp_command));
-                               strncpy(temp_command, cli.input,
-                                       cli.cursor_pos);
+                               strncpy(temp_command, hdt_cli.input,
+                                       hdt_cli.cursor_pos);
                                sprintf(key, "%c", current_key);
                                strncat(temp_command, key, 1);
                                strncat(temp_command,
-                                       cli.input + cli.cursor_pos,
+                                       hdt_cli.input + hdt_cli.cursor_pos,
                                        trailing_chars);
-                               memset(cli.input, 0, sizeof(cli.input));
-                               snprintf(cli.input, sizeof(cli.input), "%s",
+                               memset(hdt_cli.input, 0, sizeof(hdt_cli.input));
+                               snprintf(hdt_cli.input, sizeof(hdt_cli.input), "%s",
                                         temp_command);
 
                                /* Clear the end of the line */
-                               fputs("\033[0K", stdout);
+                               clear_end_of_line();
 
                                /* Print the resulting buffer */
-                               printf("%s", cli.input + cli.cursor_pos);
-                               sprintf(temp_command, "\033[%dD",
-                                       trailing_chars);
+                               printf("%s", hdt_cli.input + hdt_cli.cursor_pos);
+
                                /* Return where we must put the new char */
-                               fputs(temp_command, stdout);
+                               move_cursor_left(trailing_chars);
 
                        } else {
                                putchar(current_key);
-                               cli.input[cli.cursor_pos] = current_key;
+                               hdt_cli.input[hdt_cli.cursor_pos] = current_key;
                        }
-                       cli.cursor_pos++;
+                       hdt_cli.cursor_pos++;
                        break;
                }
        }
 }
-
-int do_exit(struct s_cli *cli)
-{
-       switch (cli->mode) {
-       case HDT_MODE:
-               return EXIT_MODE;
-       case KERNEL_MODE:
-       case PXE_MODE:
-       case SYSLINUX_MODE:
-       case PCI_MODE:
-       case DMI_MODE:
-       case VESA_MODE:
-       case CPU_MODE:
-               return HDT_MODE;
-       case EXIT_MODE:
-               return EXIT_MODE;       /* should not happen */
-       }
-       return HDT_MODE;
-}
-
-static void main_show_summary(struct s_hardware *hardware)
-{
-       detect_pci(hardware);   /* pxe is detected in the pci */
-       detect_dmi(hardware);
-       cpu_detect(hardware);
-       clear_screen();
-       main_show_cpu(hardware);
-       if (hardware->is_dmi_valid) {
-               more_printf("System\n");
-               more_printf(" Manufacturer : %s\n",
-                           hardware->dmi.system.manufacturer);
-               more_printf(" Product Name : %s\n",
-                           hardware->dmi.system.product_name);
-               more_printf(" Serial       : %s\n",
-                           hardware->dmi.system.serial);
-               more_printf("Bios\n");
-               more_printf(" Version      : %s\n", hardware->dmi.bios.version);
-               more_printf(" Release      : %s\n",
-                           hardware->dmi.bios.release_date);
-
-               int argc = 2;
-               char *argv[2] = { "0", "0" };
-               show_dmi_memory_modules(argc, argv, hardware);
-               if (hardware->dmi.ipmi.filled==true) {
-                       more_printf("IPMI baseboard v%u.%u present\n",
-                         hardware->dmi.ipmi.major_specification_version,
-                         hardware->dmi.ipmi.minor_specification_version);
-               }
-       }
-       main_show_pci(hardware);
-
-       if (hardware->is_pxe_valid)
-               main_show_pxe(hardware);
-
-       main_show_kernel(hardware);
-}
-
-void show_main_help(struct s_hardware *hardware)
-{
-       more_printf("Show supports the following commands : \n");
-       more_printf(" %s\n", CLI_SUMMARY);
-       more_printf(" %s\n", CLI_PCI);
-       more_printf(" %s\n", CLI_DMI);
-       more_printf(" %s\n", CLI_CPU);
-       more_printf(" %s\n", CLI_KERNEL);
-       more_printf(" %s\n", CLI_SYSLINUX);
-       more_printf(" %s\n", CLI_VESA);
-       more_printf(" %s\n", CLI_HDT);
-       if (hardware->sv->filesystem == SYSLINUX_FS_PXELINUX)
-               more_printf(" %s\n", CLI_PXE);
-}
-
-void main_show_hdt(struct s_hardware *hardware)
-{
-  more_printf("HDT\n");
-  more_printf(" Product     : %s\n", PRODUCT_NAME);
-  more_printf(" Version     : %s\n", VERSION);
-  more_printf(" Author      : %s\n", AUTHOR);
-  more_printf(" Contact     : %s\n", CONTACT);
-  char *contributors[NB_CONTRIBUTORS] = CONTRIBUTORS;
-  for (int c=0; c<NB_CONTRIBUTORS; c++) {
-   more_printf(" Contributor : %s\n", contributors[c]);
-  }
-}
-
-
-void main_show(char *item, struct s_hardware *hardware)
-{
-       if (!strncmp(item, CLI_SUMMARY, sizeof(CLI_SUMMARY))) {
-               main_show_summary(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_PCI, sizeof(CLI_PCI))) {
-               main_show_pci(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_DMI, sizeof(CLI_DMI))) {
-               main_show_dmi(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_CPU, sizeof(CLI_CPU))) {
-               main_show_cpu(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_PXE, sizeof(CLI_PXE))) {
-               main_show_pxe(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_SYSLINUX, sizeof(CLI_SYSLINUX))) {
-               main_show_syslinux(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_KERNEL, sizeof(CLI_KERNEL))) {
-               main_show_kernel(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_VESA, sizeof(CLI_VESA))) {
-               main_show_vesa(hardware);
-               return;
-       }
-       if (!strncmp(item, CLI_HDT, sizeof(CLI_HDT))) {
-               main_show_hdt(hardware);
-               return;
-       }
-       show_main_help(hardware);
-}
index 34ff66e..516d2fc 100644 (file)
 
 #include "hdt-common.h"
 
+#define DEBUG 0
+#if DEBUG
+# define dprintf printf
+#else
+# define dprintf(f, ...) ((void)0)
+#endif
+
+/* Declare a variable or data structure as unused. */
+#define __unused __attribute__ (( unused ))
+
 #define MAX_LINE_SIZE 256
 
 #define CLI_SPACE " "
 #define CLI_LF "\n"
+#define CLI_MENU "menu"
 #define CLI_CLEAR "clear"
 #define CLI_EXIT "exit"
 #define CLI_HELP "help"
 #define CLI_SHOW "show"
+#define CLI_SET "set"
+#define CLI_MODE "mode"
 #define CLI_HDT  "hdt"
 #define CLI_PCI  "pci"
 #define CLI_PXE  "pxe"
 #define CLI_SHOW_LIST "list"
 #define CLI_IRQ "irq"
 #define CLI_MODES "modes"
+#define CLI_VPD  "vpd"
 
 typedef enum {
-  EXIT_MODE,
-  HDT_MODE,
-  PCI_MODE,
-  DMI_MODE,
-  CPU_MODE,
-  PXE_MODE,
-  KERNEL_MODE,
-  SYSLINUX_MODE,
-  VESA_MODE,
+       INVALID_MODE,
+       EXIT_MODE,
+       HDT_MODE,
+       PCI_MODE,
+       DMI_MODE,
+       CPU_MODE,
+       PXE_MODE,
+       KERNEL_MODE,
+       SYSLINUX_MODE,
+       VESA_MODE,
+       VPD_MODE,
 } cli_mode_t;
 
 #define PROMPT_SIZE 32
 #define MAX_HISTORY_SIZE 32
 struct s_cli {
-  cli_mode_t mode;
-  char prompt[PROMPT_SIZE];
-  char input[MAX_LINE_SIZE];
-  int cursor_pos;
-  char history[MAX_HISTORY_SIZE][MAX_LINE_SIZE];
-  int history_pos;
-  int max_history_pos;
+       cli_mode_t mode;
+       char prompt[PROMPT_SIZE];
+       char input[MAX_LINE_SIZE];
+       uint8_t cursor_pos;
+       char history[MAX_HISTORY_SIZE][MAX_LINE_SIZE];
+       int history_pos;
+       int max_history_pos;
 };
-
-/* A command-line command */
-struct commands_mode {
-  const unsigned int mode;
-  struct commands_module_descr* show_modules;
-  /* Future: set? */
+struct s_cli hdt_cli;
+
+/* Describe a cli mode */
+struct cli_mode_descr {
+       const unsigned int mode;
+       const char* name;
+       /* Handle 1-token commands */
+       struct cli_module_descr* default_modules;
+       /* Handle show <module> <args> */
+       struct cli_module_descr* show_modules;
+       /* Handle set <module> <args> */
+       struct cli_module_descr* set_modules;
 };
 
-struct commands_module {
-  const char *name;
-  void ( * exec ) ( int argc, char** argv, struct s_hardware *hardware );
+/* Describe a subset of commands in a module (default, show, set, ...) */
+struct cli_module_descr {
+       struct cli_callback_descr* modules;
+       void ( * default_callback ) ( int argc, char** argv, struct s_hardware *hardware );
 };
 
-/* Describe 'show', 'set', ... commands in a module */
-struct commands_module_descr {
-  struct commands_module* modules;
-  const int nb_modules;
+/* Describe a callback (belongs to a mode and a module) */
+struct cli_callback_descr {
+       const char *name;
+       void ( * exec ) ( int argc, char** argv, struct s_hardware *hardware );
 };
 
-struct commands_mode dmi_mode;
+/* Manage aliases */
+#define MAX_ALIASES 2
+struct cli_alias {
+       const char *command;    /* Original command */
+       const int nb_aliases;   /* Size of aliases array */
+       const char **aliases;   /* List of aliases */
+};
 
+/* List of implemented modes */
+extern struct cli_mode_descr *list_modes[];
+struct cli_mode_descr hdt_mode;
+struct cli_mode_descr dmi_mode;
+struct cli_mode_descr syslinux_mode;
+struct cli_mode_descr pxe_mode;
+struct cli_mode_descr kernel_mode;
+struct cli_mode_descr cpu_mode;
+struct cli_mode_descr pci_mode;
+struct cli_mode_descr vesa_mode;
+struct cli_mode_descr vpd_mode;
+
+/* cli helpers */
+void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found);
+void find_cli_callback_descr(const char *module_name,
+                            struct cli_module_descr *modules_list,
+                            struct cli_callback_descr **module_found);
+cli_mode_t mode_s_to_mode_t(char *name);
+
+void set_mode(cli_mode_t mode, struct s_hardware *hardware);
 void start_cli_mode(struct s_hardware *hardware);
 void main_show(char *item, struct s_hardware *hardware);
-int do_exit(struct s_cli *cli);
 
 // DMI STUFF
 #define CLI_DMI_BASE_BOARD "base_board"
@@ -112,36 +160,28 @@ int do_exit(struct s_cli *cli);
 #define CLI_DMI_MEMORY_BANK "bank"
 #define CLI_DMI_PROCESSOR "cpu"
 #define CLI_DMI_SYSTEM "system"
-#define CLI_DMI_LIST CLI_SHOW_LIST
 #define CLI_DMI_IPMI "ipmi"
-#define CLI_DMI_MAX_MODULES 10
-void main_show_dmi(struct s_hardware *hardware);
-void handle_dmi_commands(char *cli_line, struct s_hardware *hardware);
+#define CLI_DMI_LIST CLI_SHOW_LIST
+void main_show_dmi(int argc, char **argv, struct s_hardware *hardware);
 void show_dmi_memory_modules(int argc, char** argv, struct s_hardware *hardware);
 
 // PCI STUFF
 #define CLI_PCI_DEVICE "device"
-void main_show_pci(struct s_hardware *hardware);
-void handle_pci_commands(char *cli_line, struct s_hardware *hardware);
+void main_show_pci(int argc, char **argv, struct s_hardware *hardware);
 void cli_detect_pci(struct s_hardware *hardware);
 
 // CPU STUFF
-void main_show_cpu(struct s_hardware *hardware);
-void handle_cpu_commands(char *cli_line, struct s_hardware *hardware);
+void main_show_cpu(int argc, char **argv, struct s_hardware *hardware);
 
 // PXE STUFF
-void main_show_pxe(struct s_hardware *hardware);
-void handle_pxe_commands(char *cli_line, struct s_hardware *hardware);
+void main_show_pxe(int argc, char **argv, struct s_hardware *hardware);
 
 // KERNEL STUFF
-void main_show_kernel(struct s_hardware *hardware);
-void handle_kernel_commands(char *cli_line, struct s_hardware *hardware);
+void main_show_kernel(int argc, char **argv, struct s_hardware *hardware);
 
 // SYSLINUX STUFF
-void main_show_syslinux(struct s_hardware *hardware);
-void handle_syslinux_commands(char *cli_line, struct s_hardware *hardware);
+void main_show_syslinux(int argc, char **argv, struct s_hardware *hardware);
 
 // VESA STUFF
-void main_show_vesa(struct s_hardware *hardware);
-void handle_vesa_commands(char *cli_line, struct s_hardware *hardware);
+void main_show_vesa(int argc, char **argv, struct s_hardware *hardware);
 #endif
index 6c2e1e4..8cda7f0 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <getkey.h>
 #include "syslinux/config.h"
 #include "../lib/sys/vesa/vesa.h"
-
 #include "hdt-common.h"
+#include "lib-ansi.h"
+
+/* ISOlinux requires a 8.3 format */
+void convert_isolinux_filename(char *filename, struct s_hardware *hardware) {
+  /* Exit if we are not running ISOLINUX */
+  if (hardware->sv->filesystem != SYSLINUX_FS_ISOLINUX) return;
+  /* Searching the dot */
+  char *dot=strchr(filename,'.');
+  /* Exiting if not dot exists in that string */
+  if (dot==NULL) return;
+  /* Exiting if the extension is 3 char or less */
+  if (strlen(dot)<=4) return;
+
+  /* We have an extension bigger than .blah
+   * so we have to shorten it to 3*/
+  dot[4]='\0';
+}
 
 void detect_parameters(const int argc, const char *argv[],
                        struct s_hardware *hardware)
@@ -41,12 +58,15 @@ void detect_parameters(const int argc, const char *argv[],
     if (!strncmp(argv[i], "modules=", 8)) {
       strncpy(hardware->modules_pcimap_path, argv[i] + 8,
         sizeof(hardware->modules_pcimap_path));
+      convert_isolinux_filename(hardware->modules_pcimap_path,hardware);
     } else if (!strncmp(argv[i], "pciids=", 7)) {
       strncpy(hardware->pciids_path, argv[i] + 7,
         sizeof(hardware->pciids_path));
+      convert_isolinux_filename(hardware->pciids_path,hardware);
     } else if (!strncmp(argv[i], "memtest=", 8)) {
       strncpy(hardware->memtest_label, argv[i] + 8,
         sizeof(hardware->memtest_label));
+      convert_isolinux_filename(hardware->memtest_label,hardware);
     }
   }
 }
@@ -86,9 +106,11 @@ void init_hardware(struct s_hardware *hardware)
   hardware->dmi_detection = false;
   hardware->pxe_detection = false;
   hardware->vesa_detection = false;
+  hardware->vpd_detection = false;
   hardware->nb_pci_devices = 0;
   hardware->is_dmi_valid = false;
   hardware->is_pxe_valid = false;
+  hardware->is_vpd_valid = false;
   hardware->pci_domain = NULL;
 
   /* Cleaning structures */
@@ -97,6 +119,7 @@ void init_hardware(struct s_hardware *hardware)
   memset(&hardware->cpu, 0, sizeof(s_cpu));
   memset(&hardware->pxe, 0, sizeof(struct s_pxe));
   memset(&hardware->vesa, 0, sizeof(struct s_vesa));
+  memset(&hardware->vpd, 0, sizeof(s_vpd));
   memset(hardware->syslinux_fs, 0, sizeof hardware->syslinux_fs);
   memset(hardware->pciids_path, 0, sizeof hardware->pciids_path);
   memset(hardware->modules_pcimap_path, 0,
@@ -126,6 +149,30 @@ int detect_dmi(struct s_hardware *hardware)
   return 0;
 }
 
+/**
+ * vpd_detection - populate the VPD structure
+ *
+ * VPD is a structure available on IBM machines.
+ * It is documented at:
+ *    http://www.pc.ibm.com/qtechinfo/MIGR-45120.html
+ * (XXX the page seems to be gone)
+ **/
+int detect_vpd(struct s_hardware *hardware)
+{
+       if (hardware->vpd_detection)
+               return -1;
+       else
+               hardware->vpd_detection = true;
+
+       if (vpd_decode(&hardware->vpd) == -ENOVPDTABLE) {
+               hardware->is_vpd_valid = false;
+               return -ENOVPDTABLE;
+       } else {
+               hardware->is_vpd_valid = true;
+               return 0;
+       }
+}
+
 /* Detection vesa stuff*/
 int detect_vesa(struct s_hardware *hardware) {
   static com32sys_t rm;
@@ -427,16 +474,76 @@ const char *find_argument(const char **argv, const char *argument)
 
 void clear_screen(void)
 {
-  fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
-  display_line_nb = 0;
+  move_cursor_to_next_line();
+  disable_utf8();
+  set_g1_special_char();
+  set_us_g0_charset();
+  display_cursor(false);
+  clear_entire_screen();
+  reset_more_printf();
+}
+
+/* remove begining spaces */
+char *skip_spaces(char *p)
+{
+  while (*p && *p <= ' ') {
+    p++;
+  }
+
+  return p;
 }
 
-/* searching the next char that is not a space */
-char *skipspace(char *p)
+/* remove trailing & begining spaces */
+char *remove_spaces(char *p)
 {
-  while (*p && *p <= ' ')
+  char *save=p;
+  p+=strlen(p)-1;
+  while (*p && *p <= ' ') {
+   *p='\0';
+   p--;
+  }
+  p=save;
+  while (*p && *p <= ' ') {
     p++;
+  }
 
   return p;
 }
 
+/* delete multiple spaces, one is enough */
+char *del_multi_spaces(char *p) {
+ /* Saving the original pointer*/
+ char *save=p;
+
+ /* Let's parse the complete string
+  * As we search for a double spacing
+  * we have to be sure then string is
+  * long enough to be processed */
+ while (*p && *p+1) {
+
+   /* If we have two consecutive spaces*/
+   if ((*p == ' ') && (*(p+1) == ' ')) {
+
+    /* Let's copy to the current position
+     * the content from the second space*/
+    strncpy(p,p+1,strlen(p+1));
+
+    /* The string is 1 char smaller*/
+    *(p+strlen(p)-1)='\0';
+
+    /* Don't increment the pointer as we
+     * changed the content of the current position*/
+    continue;
+   }
+
+   /* Nothing as been found, let's see on the next char*/
+   p++;
+ }
+ /* Returning the original pointer*/
+ return save;
+}
+
+/* Reset the more_printf counter */
+void reset_more_printf() {
+  display_line_nb=0;
+}
index dc78328..7e3dc7d 100644 (file)
@@ -36,6 +36,7 @@
 #include "dmi/dmi.h"
 #include "hdt-ata.h"
 #include "../lib/sys/vesa/vesa.h"
+#include <vpd/vpd.h>
 
 /* This two values are used for switching for the menu to the CLI mode */
 #define HDT_SWITCH_TO_CLI "hdt_switch_to_cli"
@@ -46,7 +47,7 @@ extern int display_line_nb;
 
 #define more_printf(...) do {\
  if (display_line_nb == 23) {\
-   printf("\nPress any key to continue\n");\
+   printf("Press any key to continue\n");\
    display_line_nb=0;\
    get_key(stdin, 0);\
  }\
@@ -94,6 +95,7 @@ struct s_vesa {
 struct s_hardware {
   s_dmi dmi;                      /* DMI table */
   s_cpu cpu;                      /* CPU information */
+  s_vpd vpd;                      /* VPD information */
   struct pci_domain *pci_domain;  /* PCI Devices */
   struct diskinfo disk_info[256]; /* Disk Information */
   int disks_count;               /* Number of detected disks */
@@ -106,6 +108,7 @@ struct s_hardware {
   bool is_dmi_valid;
   bool is_pxe_valid;
   bool is_vesa_valid;
+  bool is_vpd_valid;
 
   bool dmi_detection; /* Does the dmi stuff has already been detected? */
   bool pci_detection; /* Does the pci stuff has already been detected? */
@@ -113,6 +116,7 @@ struct s_hardware {
   bool disk_detection;/* Does the disk stuff has already been detected? */
   bool pxe_detection; /* Does the pxe stuff has already been detected? */
   bool vesa_detection;/* Does the vesa sutff have been already detected? */
+  bool vpd_detection; /* Does the vpd stuff has already been detected? */
 
   char syslinux_fs[22];
   const struct syslinux_version *sv;
@@ -121,9 +125,13 @@ struct s_hardware {
   char memtest_label[255];
 };
 
+void reset_more_printf();
 const char *find_argument(const char **argv, const char *argument);
-char *skipspace(char *p);
+char *remove_spaces(char *p);
+char *skip_spaces(char *p);
+char *del_multi_spaces(char *p);
 int detect_dmi(struct s_hardware *hardware);
+int detect_vpd(struct s_hardware *hardware);
 void detect_disks(struct s_hardware *hardware);
 void detect_pci(struct s_hardware *hardware);
 void cpu_detect(struct s_hardware *hardware);
index 3915f2b..a3a3a8e 100644 (file)
@@ -126,9 +126,9 @@ void compute_chassis(struct s_my_menu *menu, s_dmi * dmi)
   menu->items_count++;
 
   snprintf(buffer, sizeof buffer, "Asset Tag : %s",
-     dmi->chassis.asset_tag);
+     del_multi_spaces(dmi->chassis.asset_tag));
   snprintf(statbuffer, sizeof statbuffer, "Asset Tag: %s",
-     dmi->chassis.asset_tag);
+     del_multi_spaces(dmi->chassis.asset_tag));
   add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
   menu->items_count++;
 
@@ -405,7 +405,7 @@ void compute_ipmi(struct s_my_menu *menu, s_dmi * dmi)
   snprintf(buffer, sizeof buffer, "Spec. Version   : %u.%u",
       dmi->ipmi.major_specification_version,
       dmi->ipmi.minor_specification_version);
-  snprintf(statbuffer, sizeof statbuffer, "Specification Version: %u.u",
+  snprintf(statbuffer, sizeof statbuffer, "Specification Version: %u.%u",
       dmi->ipmi.major_specification_version,
       dmi->ipmi.minor_specification_version);
   add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
@@ -524,7 +524,7 @@ void compute_battery(struct s_my_menu *menu, s_dmi * dmi)
 
   snprintf(buffer, sizeof buffer, "Maximum Error   : %s",
      dmi->battery.maximum_error);
-  snprintf(statbuffer, sizeof statbuffer, "Maximum Error (%) : %s",
+  snprintf(statbuffer, sizeof statbuffer, "Maximum Error (percent) : %s",
      dmi->battery.maximum_error);
   add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
   menu->items_count++;
index d71fbe1..a30cf0f 100644 (file)
@@ -45,9 +45,9 @@ void compute_processor(struct s_my_menu *menu, struct s_hardware *hardware)
   add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
   menu->items_count++;
 
-  snprintf(buffer, sizeof buffer, "Model     : %s", hardware->cpu.model);
+  snprintf(buffer, sizeof buffer, "Model     : %s", del_multi_spaces(hardware->cpu.model));
   snprintf(statbuffer, sizeof statbuffer, "Model: %s",
-     hardware->cpu.model);
+     del_multi_spaces(hardware->cpu.model));
   add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
   menu->items_count++;
 
diff --git a/com32/hdt/hdt-menu-vpd.c b/com32/hdt/hdt-menu-vpd.c
new file mode 100644 (file)
index 0000000..817c107
--- /dev/null
@@ -0,0 +1,100 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+ */
+
+#include "hdt-menu.h"
+
+/**
+ * compute_vpd - generate vpd menu
+ **/
+void compute_vpd(struct s_my_menu *menu, struct s_hardware *hardware)
+{
+       char buffer[SUBMENULEN + 1];
+       char statbuffer[STATLEN + 1];   /* Status bar */
+
+       menu->menu = add_menu(" VPD ", -1);
+       menu->items_count = 0;
+       set_menu_pos(SUBMENU_Y, SUBMENU_X);
+
+       snprintf(buffer, sizeof buffer, "Address                  : %s",
+                hardware->vpd.base_address);
+       snprintf(statbuffer, sizeof statbuffer, "Address: %s",
+                hardware->cpu.vendor);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Bios Build ID            : %s",
+                hardware->vpd.bios_build_id);
+       snprintf(statbuffer, sizeof statbuffer, "Bios Build ID: %s",
+                hardware->vpd.bios_build_id);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Bios Release Date        : %s",
+                hardware->vpd.bios_release_date);
+       snprintf(statbuffer, sizeof statbuffer, "Bios Release Date: %s",
+                hardware->vpd.bios_release_date);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Bios Version             : %s",
+                hardware->vpd.bios_version);
+       snprintf(statbuffer, sizeof statbuffer, "Bios Version: %s",
+                hardware->vpd.bios_version);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Default Flash Filename   : %s",
+                hardware->vpd.default_flash_filename);
+       snprintf(statbuffer, sizeof statbuffer, "Default Flash Filename: %s",
+                hardware->vpd.default_flash_filename);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Box Serial Number        : %s",
+                hardware->vpd.box_serial_number);
+       snprintf(statbuffer, sizeof statbuffer, "Box Serial Number: %s",
+                hardware->vpd.box_serial_number);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Motherboard Serial Number: %s",
+                hardware->vpd.motherboard_serial_number);
+       snprintf(statbuffer, sizeof statbuffer, "Motherboard Serial Number: %s",
+                hardware->vpd.motherboard_serial_number);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       snprintf(buffer, sizeof buffer, "Machine Type/Model       : %s",
+                hardware->vpd.machine_type_model);
+       snprintf(statbuffer, sizeof statbuffer, "Machine Type/Model: %s",
+                hardware->vpd.machine_type_model);
+       add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+       menu->items_count++;
+
+       printf("MENU: VPD menu done (%d items)\n", menu->items_count);
+}
index b531bc7..18158ae 100644 (file)
@@ -112,7 +112,7 @@ void setup_menu(char *version)
 {
   /* Creating the menu */
   init_menusystem(version);
-  set_window_size(0, 0, 24, 80);
+  set_window_size(0, 0, 25, 80);
 
   /* Register the menusystem handler */
   // reg_handler(HDLR_SCREEN,&msys_handler);
@@ -153,6 +153,7 @@ void compute_submenus(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware)
   }
 
   compute_processor(&(hdt_menu->cpu_menu), hardware);
+  compute_vpd(&(hdt_menu->vpd_menu), hardware);
   compute_disks(hdt_menu, hardware->disk_info, hardware);
 
 #ifdef WITH_PCI
@@ -242,6 +243,12 @@ void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware)
     }
   }
 
+ if (hardware->is_vpd_valid == true) {
+   add_item("VPD","VPD Information Menu", OPT_SUBMENU, NULL,
+      hdt_menu->vpd_menu.menu);
+   hdt_menu->main_menu.items_count++;
+  }
+
   if (hardware->is_pxe_valid == true) {
     add_item("P<X>E", "PXE Information Menu", OPT_SUBMENU, NULL,
        hdt_menu->pxe_menu.menu);
@@ -299,6 +306,10 @@ void detect_hardware(struct s_hardware *hardware)
            hardware->dmi.dmitable.major_version,
            hardware->dmi.dmitable.minor_version);
   }
+
+  printf("VPD: Detecting\n");
+  detect_vpd(hardware);
+
 #ifdef WITH_PCI
   detect_pci(hardware);
   printf("PCI: %d Devices Found\n", hardware->nb_pci_devices);
index 91809e2..70fdb38 100644 (file)
@@ -77,6 +77,7 @@ struct s_hdt_menu {
   struct s_my_menu vesa_menu;
   struct s_my_menu vesa_card_menu;
   struct s_my_menu vesa_modes_menu;
+  struct s_my_menu vpd_menu;
   int total_menu_count; // Sum of all menus we have
 };
 
@@ -103,6 +104,9 @@ void compute_bios(struct s_my_menu *menu, s_dmi * dmi);
 void compute_memory(struct s_hdt_menu *menu, s_dmi * dmi, struct s_hardware *hardware);
 void compute_ipmi(struct s_my_menu *menu, s_dmi * dmi);
 
+// VPD Stuff
+void compute_vpd(struct s_my_menu *menu, struct s_hardware *hardware);
+
 // Processor Stuff
 void compute_processor(struct s_my_menu *menu, struct s_hardware *hardware);
 
index 467fe1c..a2b9b53 100644 (file)
@@ -51,16 +51,17 @@ int main(const int argc, const char *argv[])
   snprintf(version_string, sizeof version_string, "%s %s by %s",
            PRODUCT_NAME,VERSION,AUTHOR);
 
+  console_ansi_raw();
+
   /* Cleaning structures */
   init_hardware(&hardware);
 
-  /* Detecting parameters */
-  detect_parameters(argc, argv, &hardware);
-
   /* Detecting Syslinux version */
   detect_syslinux(&hardware);
 
-  console_ansi_raw();
+  /* Detecting parameters */
+  detect_parameters(argc, argv, &hardware);
+
   /* Opening the Syslinux console */
 //  openconsole(&dev_stdcon_r, &dev_ansicon_w);
 
index 14c94b3..dfcb436 100644 (file)
@@ -31,8 +31,8 @@
 
 #define PRODUCT_NAME "Hardware Detection Tool"
 #define AUTHOR "Erwan Velu"
-#define CONTACT "erwan(dot)velu(point)free(dot)fr"
-#define VERSION "0.2.7"
+#define CONTACT "hdt@zytor.com"
+#define VERSION "0.3.1"
 #define NB_CONTRIBUTORS 2
 #define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"}
 
diff --git a/com32/hdt/lib-ansi.c b/com32/hdt/lib-ansi.c
new file mode 100644 (file)
index 0000000..12e5ecc
--- /dev/null
@@ -0,0 +1,97 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+ *  Ansi Sequences can be found here :
+ *  http://ascii-table.com/ansi-escape-sequences-vt-100.php
+ *  http://en.wikipedia.org/wiki/ANSI_escape_code
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+void display_cursor(bool status)
+{
+       if (status == true) {
+               fputs("\033[?25h", stdout);
+       } else {
+               fputs("\033[?25l", stdout);
+       }
+}
+
+void clear_end_of_line() {
+       fputs("\033[0K", stdout);
+}
+
+void move_cursor_left(int count) {
+       char buffer[10];
+       memset(buffer,0,sizeof(buffer));
+       sprintf(buffer,"\033[%dD",count);
+       fputs(buffer, stdout);
+}
+
+void move_cursor_right(int count) {
+       char buffer[10];
+       memset(buffer,0,sizeof(buffer));
+       sprintf(buffer,"\033[%dC",count);
+       fputs(buffer, stdout);
+}
+
+void clear_line() {
+       fputs("\033[2K", stdout);
+}
+
+void clear_beginning_of_line() {
+       fputs("\033[1K", stdout);
+}
+
+void move_cursor_to_column(int count) {
+       char buffer[10];
+        memset(buffer,0,sizeof(buffer));
+       sprintf(buffer,"\033[%dG",count);
+       fputs(buffer, stdout);
+}
+
+void move_cursor_to_next_line() {
+       fputs("\033e", stdout);
+}
+
+void disable_utf8() {
+       fputs("\033%@", stdout);
+}
+
+void set_g1_special_char(){
+       fputs("\033)0", stdout);
+}
+
+void set_us_g0_charset() {
+       fputs("\033(B\1#0", stdout);
+}
+
+void clear_entire_screen() {
+       fputs("\033[2J", stdout);
+}
diff --git a/com32/hdt/lib-ansi.h b/com32/hdt/lib-ansi.h
new file mode 100644 (file)
index 0000000..2a17766
--- /dev/null
@@ -0,0 +1,43 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Erwan Velu - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * -----------------------------------------------------------------------
+ */
+
+#ifndef DEFINE_LIB_ANSI_H
+#define DEFINE_LIB_ANSI_H
+void display_cursor(bool status);
+void clear_end_of_line();
+void move_cursor_left(int count);
+void move_cursor_right(int count);
+void clear_line();
+void clear_beginning_of_line();
+void move_cursor_to_column(int count);
+void move_cursor_to_next_line();
+void disable_utf8();
+void set_g1_special_char();
+void set_us_g0_charset();
+void clear_entire_screen();
+#endif
index 44cd573..da2edfb 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------- *
- *   
+ *
  *   Copyright 2002-2009 H. Peter Anvin - All Rights Reserved
  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
  *
  *   sell copies of the Software, and to permit persons to whom
  *   the Software is furnished to do so, subject to the following
  *   conditions:
- *   
+ *
  *   The above copyright notice and this permission notice shall
  *   be included in all copies or substantial portions of the Software.
- *   
+ *
  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
index dcc4abf..fcae2da 100644 (file)
@@ -65,7 +65,7 @@ static inline __constfunc uint32_t cpuid_edx(uint32_t level)
 static inline __constfunc bool cpu_has_eflag(uint32_t flag)
 {
   uint32_t f1, f2;
-  
+
   asm("pushfl\n\t"
       "pushfl\n\t"
       "popl %0\n\t"
@@ -78,7 +78,7 @@ static inline __constfunc bool cpu_has_eflag(uint32_t flag)
       "popfl\n\t"
       : "=&r" (f1), "=&r" (f2)
       : "ir" (flag));
-  
+
   return ((f1^f2) & flag) != 0;
 }
 
index b44db62..b6556ff 100644 (file)
@@ -4,13 +4,13 @@
 #include <inttypes.h>
 #include <sys/io.h>
 
-#define MAX_PCI_FUNC             8
-#define MAX_PCI_DEVICES         32
-#define MAX_PCI_BUSES          256
+#define MAX_PCI_FUNC             8
+#define MAX_PCI_DEVICES                 32
+#define MAX_PCI_BUSES          256
 #define LINUX_KERNEL_MODULE_SIZE 64
-#define PCI_VENDOR_NAME_SIZE   256
-#define PCI_PRODUCT_NAME_SIZE  256
-#define PCI_CLASS_NAME_SIZE    256
+#define PCI_VENDOR_NAME_SIZE   256
+#define PCI_PRODUCT_NAME_SIZE  256
+#define PCI_CLASS_NAME_SIZE    256
 #define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10
 #define MAX_PCI_CLASSES                256
 
index 66bdbbd..304c081 100644 (file)
@@ -1,6 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
  *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
@@ -35,6 +36,7 @@
 #define _SYSLINUX_BOOTRM_H
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <com32.h>
 #include <syslinux/movebits.h>
 
@@ -60,6 +62,8 @@ struct syslinux_rm_regs {
 
   uint16_t ip;                 /* Offset 44 */
   uint16_t cs;                 /* Offset 46 */
+
+  bool sti;                    /* Offset 48 */
 };
 
 int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist,
index 8f21ad0..290cff3 100644 (file)
@@ -50,4 +50,3 @@ syslinux_keyboard_map(void)
 }
 
 #endif /* _SYSLINUX_KEYBOARD_H */
-
index f35ef22..f0cb277 100644 (file)
@@ -59,8 +59,13 @@ int syslinux_add_movelist(struct syslinux_movelist **,
                          addr_t dst, addr_t src, addr_t len);
 int syslinux_allocate_from_list(struct syslinux_movelist **freelist,
                                addr_t dst, addr_t len);
-int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
-                            struct syslinux_memmap *memmap);
+int syslinux_do_shuffle(struct syslinux_movelist *fraglist,
+                       struct syslinux_memmap *memmap,
+                       addr_t entry_point, addr_t entry_type,
+                       uint16_t bootflags);
+struct syslinux_memmap *
+syslinux_target_memmap(struct syslinux_movelist *fraglist,
+                      struct syslinux_memmap *memmap);
 
 /* Operatons on struct syslinux_memmap */
 struct syslinux_memmap *syslinux_init_memmap(void);
@@ -74,6 +79,9 @@ int syslinux_memmap_largest(struct syslinux_memmap *list,
                            addr_t *start, addr_t *len);
 void syslinux_free_memmap(struct syslinux_memmap *list);
 struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list);
+int syslinux_memmap_find(struct syslinux_memmap *list,
+                        enum syslinux_memmap_types type,
+                        addr_t *start, addr_t *len, addr_t align);
 
 /* Debugging functions */
 void syslinux_dump_movelist(FILE *file, struct syslinux_movelist *ml);
index 983a3c5..e70b8c9 100644 (file)
@@ -53,4 +53,3 @@ struct free_arena_header {
 
 extern struct free_arena_header __malloc_head;
 void __inject_free_block(struct free_arena_header *ah);
-
index 5f2c4ec..6b986a0 100644 (file)
@@ -80,7 +80,7 @@ memcpy:
        popl    %eax            /* Return value */
        popl    %edi
        popl    %esi
-1:     
+1:
        ret
 
        .size   memcpy, .-memcpy
index 90bbf3b..2fcb4b5 100644 (file)
@@ -41,7 +41,7 @@ memmove:
        pushl   %esi
        pushl   %edi
        pushl   %eax            /* Return value */
-       
+
        movl    %eax,%edi
        movl    %edx,%esi
 
index f6961f6..cad7b98 100644 (file)
@@ -79,7 +79,7 @@ mempcpy:
        movl    %edi,%eax       /* Return value */
        popl    %edi
        popl    %esi
-1:     
+1:
        ret
 
        .size   mempcpy, .-mempcpy
index 4b2583c..e641415 100644 (file)
@@ -47,7 +47,7 @@ memset:
        movzwl  %dx,%eax
        shll    $16,%edx
        orl     %edx,%eax
-       
+
        /* Initial alignment */
        movl    %edi,%edx
        shrl    $1,%edx
index a368b78..658df48 100644 (file)
@@ -7,7 +7,7 @@
  *
  * The jmp_buf is assumed to contain the following, in order:
  *     %ebx
- *     %esp
+ *     %esp
  *     %ebp
  *     %esi
  *     %edi
index 7bdc8cb..3322ab2 100644 (file)
@@ -242,7 +242,7 @@ ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count)
 void __ansicon_beep(void)
 {
   static com32sys_t ireg;
-  
+
   ireg.eax.w[0] = 0x0e07;
   ireg.ebx.b[1] = BIOS_PAGE;
   __intcall(0x10, &ireg, NULL);
index a5fdea3..170168b 100644 (file)
@@ -1,7 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
  *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
- *   Copyright 2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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 +51,6 @@ static int syslinux_memory_map_callback(void *map, addr_t start,
 struct syslinux_memmap *syslinux_memory_map(void)
 {
   struct syslinux_memmap *mmap;
-  enum syslinux_memmap_types type;
-  int rv;
 
   mmap = syslinux_init_memmap();
   if (!mmap)
index d754128..782f634 100644 (file)
@@ -50,21 +50,29 @@ struct e820_entry {
 
 int syslinux_scan_memory(scan_memory_callback_t callback, void *data)
 {
-  static com32sys_t ireg, zireg;
+  static com32sys_t ireg;
   com32sys_t oreg;
   struct e820_entry *e820buf = __com32.cs_bounce;
   uint64_t start, len, maxlen;
   int memfound = 0;
   int rv;
-
-  /* Use INT 12h to get DOS memory above 0x7c00 */
-  __intcall(0x12, &zireg, &oreg);
-  if (oreg.eax.w[0] >= 32 && oreg.eax.w[0] <= 640) {
-    addr_t dosmem = (oreg.eax.w[0] << 10) - 0x7c00;
-    rv = callback(data, 0x7c00, dosmem, true);
-    if (rv)
-      return rv;
+  addr_t dosmem;
+
+  /* Use INT 12h to get DOS memory above 0x504 */
+  __intcall(0x12, &__com32_zero_regs, &oreg);
+  dosmem = oreg.eax.w[0] << 10;
+  if (dosmem < 32*1024 || dosmem > 640*1024) {
+    /* INT 12h reports nonsense... now what? */
+    uint16_t ebda_seg = (uint16_t *)0x40e;
+    if (ebda_seg >= 0x8000 && ebda_seg < 0xa000)
+      dosmem = ebda_seg << 4;
+    else
+      dosmem = 640*1024;      /* Hope for the best... */
   }
+  dosmem = (oreg.eax.w[0] << 10) - 0x510;
+  rv = callback(data, 0x510, dosmem, true);
+  if (rv)
+    return rv;
 
   /* First try INT 15h AX=E820h */
   ireg.eax.l    = 0xe820;
index d807998..196fc64 100644 (file)
@@ -63,33 +63,42 @@ struct shuffle_descriptor {
   uint32_t dst, src, len;
 };
 
-static int desc_block_size;
+static int shuffler_size;
 
-static void __constructor __syslinux_get_desc_block_size(void)
+static void __constructor __syslinux_get_shuffer_size(void)
 {
   static com32sys_t reg;
 
-  reg.eax.w[0] = 0x0011;
+  reg.eax.w[0] = 0x0023;
   __intcall(0x22, &reg, &reg);
 
-  desc_block_size = (reg.eflags.l & EFLAGS_CF) ? 64 : reg.ecx.w[0];
+  shuffler_size = (reg.eflags.l & EFLAGS_CF) ? 2048 : reg.ecx.w[0];
 }
 
-/* Allocate descriptor memory in these chunks */
-#define DESC_BLOCK_SIZE        desc_block_size
+/*
+ * Allocate descriptor memory in these chunks; if this is large we may
+ * waste memory, if it is small we may get slow convergence.
+ */
+#define DESC_BLOCK_SIZE        256
 
-int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
-                            struct syslinux_memmap *memmap)
+int syslinux_do_shuffle(struct syslinux_movelist *fraglist,
+                       struct syslinux_memmap *memmap,
+                       addr_t entry_point, addr_t entry_type,
+                       uint16_t bootflags)
 {
+  int rv = -1;
   struct syslinux_movelist *moves = NULL, *mp;
   struct syslinux_memmap *rxmap = NULL, *ml;
   struct shuffle_descriptor *dp, *dbuf;
-  int np, nb, nl, rv = -1;
+  int np;
   int desc_blocks, need_blocks;
   int need_ptrs;
   addr_t desczone, descfree, descaddr, descoffs;
   int nmoves, nzero;
-  struct shuffle_descriptor primaries[2];
+  com32sys_t ireg;
+
+  descaddr = 0;
+  dp = dbuf = NULL;
 
   /* Count the number of zero operations */
   nzero = 0;
@@ -99,11 +108,15 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
   }
 
   /* Find the largest contiguous region unused by input *and* output;
-     this is where we put the move descriptor list */
+     this is where we put the move descriptor list and safe area */
 
   rxmap = syslinux_dup_memmap(memmap);
   if (!rxmap)
     goto bail;
+  /* Avoid using the low 1 MB for the shuffle area -- this avoids
+     possible interference with the real mode code or stack */
+  if (syslinux_add_memmap(&rxmap, 0, 1024*1024, SMT_RESERVED))
+    goto bail;
   for (mp = fraglist; mp; mp = mp->next) {
     if (syslinux_add_memmap(&rxmap, mp->src, mp->len, SMT_ALLOC) ||
        syslinux_add_memmap(&rxmap, mp->dst, mp->len, SMT_ALLOC))
@@ -120,10 +133,13 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
   if (!rxmap)
     goto bail;
 
-  desc_blocks = (nzero+DESC_BLOCK_SIZE-1)/(DESC_BLOCK_SIZE-1);
+  desc_blocks = (nzero+DESC_BLOCK_SIZE-1)/DESC_BLOCK_SIZE;
   for (;;) {
+    /* We want (desc_blocks) allocation blocks, plus the terminating
+       descriptor, plus the shuffler safe area. */
     addr_t descmem = desc_blocks*
-      sizeof(struct shuffle_descriptor)*DESC_BLOCK_SIZE;
+      sizeof(struct shuffle_descriptor)*DESC_BLOCK_SIZE
+      + sizeof(struct shuffle_descriptor) + shuffler_size;
 
     if (descfree < descmem)
       goto bail;               /* No memory block large enough */
@@ -144,7 +160,7 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
     for (mp = moves; mp; mp = mp->next)
       nmoves++;
 
-    need_blocks = (nmoves+nzero+DESC_BLOCK_SIZE-1)/(DESC_BLOCK_SIZE-1);
+    need_blocks = (nmoves+nzero+DESC_BLOCK_SIZE-1)/DESC_BLOCK_SIZE;
 
     if (desc_blocks >= need_blocks)
       break;                   /* Sufficient memory, yay */
@@ -160,7 +176,7 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
   syslinux_free_memmap(rxmap);
   rxmap = NULL;
 
-  need_ptrs = nmoves+nzero+desc_blocks-1;
+  need_ptrs = nmoves+nzero+1;
   dbuf = malloc(need_ptrs*sizeof(struct shuffle_descriptor));
   if (!dbuf)
     goto bail;
@@ -174,71 +190,38 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
 
   /* Copy the move sequence into the descriptor buffer */
   np = 0;
-  nb = 0;
-  nl = nmoves+nzero;
   dp = dbuf;
   for (mp = moves; mp; mp = mp->next) {
-    if (nb == DESC_BLOCK_SIZE-1) {
-      dp->dst = -1;            /* Load new descriptors */
-      dp->src = (addr_t)(dp+1) + descoffs;
-      dp->len = sizeof(*dp)*min(nl, DESC_BLOCK_SIZE);
-      dprintf("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len);
-      dp++; np++;
-      nb = 0;
-    }
-
     dp->dst = mp->dst;
     dp->src = mp->src;
     dp->len = mp->len;
     dprintf2("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len);
-    dp++; np++; nb++; nl--;
+    dp++; np++;
   }
 
   /* Copy bzero operations into the descriptor buffer */
   for (ml = memmap; ml->type != SMT_END; ml = ml->next) {
     if (ml->type == SMT_ZERO) {
-      if (nb == DESC_BLOCK_SIZE-1) {
-       dp->dst = (addr_t)-1;   /* Load new descriptors */
-       dp->src = (addr_t)(dp+1) + descoffs;
-       dp->len = sizeof(*dp)*min(nl, DESC_BLOCK_SIZE);
-       dprintf("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len);
-       dp++; np++;
-       nb = 0;
-      }
-
       dp->dst = ml->start;
       dp->src = (addr_t)-1;    /* bzero region */
       dp->len = ml->next->start - ml->start;
       dprintf2("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len);
-      dp++; np++; nb++; nl--;
+      dp++; np++;
     }
   }
 
+  /* Finally, record the termination entry */
+  dp->dst = entry_point;
+  dp->src = entry_type;
+  dp->len = 0;
+  dp++; np++;
+
   if (np != need_ptrs) {
     dprintf("!!! np = %d : nmoves = %d, nzero = %d, desc_blocks = %d\n",
            np, nmoves, nzero, desc_blocks);
   }
 
-  /* Set up the primary descriptors in the bounce buffer.
-     The first one moves the descriptor list into its designated safe
-     zone, the second one loads the first descriptor block. */
-  dp = primaries;
-
-  dp->dst = descaddr;
-  dp->src = (addr_t)dbuf;
-  dp->len = np*sizeof(*dp);
-  dprintf("< %08x %08x %08x >\n", dp->dst, dp->src, dp->len);
-  dp++;
-
-  dp->dst = (addr_t)-1;
-  dp->src = descaddr;
-  dp->len = sizeof(*dp)*min(np, DESC_BLOCK_SIZE);
-  dprintf("< %08x %08x %08x >\n", dp->dst, dp->src, dp->len);
-  dp++;
-
-  memcpy(__com32.cs_bounce, primaries, 2*sizeof(*dp));
-
-  rv = 2;                      /* Always two primaries */
+  rv = 0;
 
  bail:
   /* This is safe only because free() doesn't use the bounce buffer!!!! */
@@ -247,5 +230,42 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist,
   if (rxmap)
     syslinux_free_memmap(rxmap);
 
-  return rv;
+  if (rv)
+    return rv;
+
+  /* Actually do it... */
+  memset(&ireg, 0, sizeof ireg);
+  ireg.edi.l = descaddr;
+  ireg.esi.l = (addr_t)dbuf;
+  ireg.ecx.l = (addr_t)dp-(addr_t)dbuf;
+  ireg.edx.w[0] = bootflags;
+  ireg.eax.w[0] = 0x0024;
+  __intcall(0x22, &ireg, NULL);
+
+  return -1;                   /* Shouldn't have returned! */
+}
+
+/*
+ * Common helper routine: takes a memory map and blots out the
+ * zones which are used in the destination of a fraglist
+ */
+struct syslinux_memmap *
+syslinux_target_memmap(struct syslinux_movelist *fraglist,
+                      struct syslinux_memmap *memmap)
+{
+  struct syslinux_memmap *tmap;
+  struct syslinux_movelist *mp;
+
+  tmap = syslinux_dup_memmap(memmap);
+  if (!tmap)
+    return NULL;
+
+  for (mp = fraglist; mp; mp = mp->next) {
+    if (syslinux_add_memmap(&tmap, mp->dst, mp->len, SMT_ALLOC)) {
+      syslinux_free_memmap(tmap);
+      return NULL;
+    }
+  }
+
+  return tmap;
 }
index d19d01b..6984763 100644 (file)
@@ -1,6 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
@@ -46,24 +47,38 @@ int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist,
   int nd;
   com32sys_t ireg;
   char *regbuf;
+  uint8_t handoff_code[9*5], *p;
+  const uint32_t *rp;
+  int i, rv;
+  struct syslinux_memmap *tmap;
+  addr_t regstub, stublen, safe;
 
-  nd = syslinux_prepare_shuffle(fraglist, memmap);
-  if (nd < 0)
+  tmap = syslinux_target_memmap(fraglist, memmap);
+  if (!tmap)
     return -1;
 
-  regbuf = (char *)__com32.cs_bounce + (12*nd);
-  memcpy(regbuf, regs, sizeof(*regs));
+  regstub = 0x800;             /* Locate anywhere above this point */
+  stublen = sizeof handoff_code;
+  rv = syslinux_memmap_find(tmap, SMT_FREE, &regstub, &stublen, 1);
+  syslinux_free_memmap(tmap);
+  if (rv)
+    return -1;
 
-  memset(&ireg, 0, sizeof ireg);
+  /* Build register-setting stub */
+  p = handoff_code;
+  rp = (const uint32_t *)regs;
+  for (i = 0; i < 8; i++) {
+    *p = 0xb8 + i;             /* MOV gpr,imm32 */
+    *(uint32_t *)(p+1) = *rp++;
+    p += 5;
+  }
+  *p = 0xe9;                   /* JMP */
+  *(uint32_t *)(p+1) = regs->eip - regstub - sizeof handoff_code;
 
-  ireg.eax.w[0] = 0x001a;
-  ireg.edx.w[0] = bootflags;
-  ireg.es       = SEG(__com32.cs_bounce);
-  ireg.edi.l    = OFFS(__com32.cs_bounce);
-  ireg.ecx.l    = nd;
-  ireg.ds       = SEG(regbuf);
-  ireg.esi.l    = OFFS(regbuf);
-  __intcall(0x22, &ireg, NULL);
+  /* Add register-setting stub to shuffle list */
+  if (syslinux_add_movelist(&fraglist, regstub, (addr_t)handoff_code,
+                           sizeof handoff_code))
+    return -1;
 
-  return -1;                   /* Too many descriptors? */
+  return syslinux_do_shuffle(fraglist, memmap, regstub, 1, bootflags);
 }
index e9226a8..5d79cad 100644 (file)
@@ -1,6 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
 #include <syslinux/movebits.h>
 #include <syslinux/bootrm.h>
 
+enum gpr_index { R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI };
+enum seg_index { R_ES, R_CS, R_SS, R_DS, R_FS, R_GS };
+
+#define ST8(P,V)                                               \
+  do {                                                         \
+    uint8_t *_p = (void *)(P);                                 \
+    *_p++ = (V);                                               \
+    (P) = (void *)_p;                                          \
+  } while (0);
+#define ST16(P,V)                                              \
+  do {                                                         \
+    uint16_t *_p = (void *)(P);                                        \
+    *_p++ = (V);                                               \
+    (P) = (void *)_p;                                          \
+  } while (0)
+#define ST32(P,V)                                              \
+  do {                                                         \
+    uint32_t *_p = (void *)(P);                                        \
+    *_p++ = (V);                                               \
+    (P) = (void *)_p;                                          \
+  } while (0)
+
+#define MOV_TO_SEG(P,S,R)                                      \
+    ST16(P, 0xc08e + ((R) << 8) + ((S) << 11))
+#define MOV_TO_R16(P,R,V)                                      \
+  do {                                                         \
+    ST8(P, 0xb8 + (R));                                                \
+    ST16(P, V);                                                        \
+  }  while (0)
+#define MOV_TO_R32(P,R,V)                                      \
+  do {                                                         \
+    ST16(P, 0xb866 + ((R) << 8));                              \
+    ST32(P, V);                                                        \
+  } while (0)
+
 int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist,
                             struct syslinux_memmap *memmap,
                             uint16_t bootflags,
                             struct syslinux_rm_regs *regs)
 {
-  int nd;
-  com32sys_t ireg;
-  char *regbuf;
+  const struct syslinux_rm_regs_alt {
+    uint16_t seg[6];
+    uint32_t gpr[8];
+    uint32_t csip;
+    bool sti;
+  } *rp;
+  int i, rv;
+  uint8_t handoff_code[8+5*5+8*6+1+5], *p;
+  uint16_t off;
+  struct syslinux_memmap *tmap;
+  addr_t regstub, stublen;
+  /* Assign GPRs for each sreg, don't use AX and SP */
+  static const uint8_t gpr_for_seg[6] = { R_CX, R_DX, R_BX, R_BP, R_SI, R_DI };
+
+  tmap = syslinux_target_memmap(fraglist, memmap);
+  if (!tmap)
+    return -1;
+
+  /*
+   * Search for a good place to put the real-mode register stub.
+   * We prefer it as low as possible above 0x800.  KVM barfs horribly
+   * if we're not aligned to a paragraph boundary, so set the alignment
+   * appropriately.
+   */
+  regstub = 0x800;
+  stublen = sizeof handoff_code;
+  rv = syslinux_memmap_find(tmap, SMT_FREE, &regstub, &stublen, 16);
+
+  if (rv || (regstub > 0x100000 - sizeof handoff_code)) {
+    /*
+     * Uh-oh.  This isn't real-mode accessible memory.
+     * It might be possible to do something insane here like
+     * putting the stub in the IRQ vectors, or in the 0x5xx segment.
+     * This code tries the 0x510-0x7ff range and hopes for the best.
+     */
+    regstub = 0x510;           /* Try the 0x5xx segment... */
+    stublen = sizeof handoff_code;
+    rv = syslinux_memmap_find(tmap, SMT_FREE, &regstub, &stublen, 16);
+
+    if (!rv && (regstub > 0x100000 - sizeof handoff_code))
+      rv = -1;                 /* No acceptable memory found */
+  }
 
-  nd = syslinux_prepare_shuffle(fraglist, memmap);
-  if (nd < 0)
+  syslinux_free_memmap(tmap);
+  if (rv)
     return -1;
 
-  regbuf = (char *)__com32.cs_bounce + (12*nd);
-  memcpy(regbuf, regs, sizeof(*regs));
+  /* Build register-setting stub */
+  p = handoff_code;
+  rp = (const struct syslinux_rm_regs_alt *)regs;
 
-  memset(&ireg, 0, sizeof ireg);
+  /* Set up GPRs with segment registers - don't use AX */
+  for (i = 0; i < 6; i++) {
+    if (i != R_CS)
+      MOV_TO_R16(p, gpr_for_seg[i], rp->seg[i]);
+  }
 
-  ireg.eax.w[0] = 0x001b;
-  ireg.edx.w[0] = bootflags;
-  ireg.es       = SEG(__com32.cs_bounce);
-  ireg.edi.l    = OFFS(__com32.cs_bounce);
-  ireg.ecx.l    = nd;
-  ireg.ds       = SEG(regbuf);
-  ireg.esi.l    = OFFS(regbuf);
-  __intcall(0x22, &ireg, NULL);
+  /* Actual transition to real mode */
+  ST32(p, 0xeac0220f);                 /* MOV CR0,EAX; JMP FAR */
+  off = (p-handoff_code)+4;
+  ST16(p, off);                                /* Offset */
+  ST16(p,regstub >> 4);                        /* Segment */
+
+  /* Load SS and ESP immediately */
+  MOV_TO_SEG(p, R_SS, R_BX);
+  MOV_TO_R32(p, R_SP, rp->seg[R_SP]);
+
+  /* Load the other segments */
+  MOV_TO_SEG(p, R_ES, R_CX);
+  MOV_TO_SEG(p, R_DS, R_BP);
+  MOV_TO_SEG(p, R_FS, R_SI);
+  MOV_TO_SEG(p, R_GS, R_DI);
+
+  for (i = 0; i < 8; i++) {
+    if (i != R_SP)
+      MOV_TO_R32(p, i, rp->gpr[i]);
+  }
+
+  ST8(p, rp->sti ? 0xfb : 0xfa);       /* STI/CLI */
+
+  ST8(p, 0xea);                                /* JMP FAR */
+  ST32(p, rp->csip);
+
+  /* Add register-setting stub to shuffle list */
+  if (syslinux_add_movelist(&fraglist, regstub, (addr_t)handoff_code,
+                           sizeof handoff_code))
+    return -1;
 
-  return -1;                   /* Too many descriptors? */
+  return syslinux_do_shuffle(fraglist, memmap, regstub, 0, bootflags);
 }
index 62b1cf3..d65d274 100644 (file)
@@ -1,6 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
@@ -36,6 +37,7 @@
  */
 
 #include <stdlib.h>
+#include <syslinux/align.h>
 #include <syslinux/movebits.h>
 
 /*
@@ -200,6 +202,39 @@ int syslinux_memmap_largest(struct syslinux_memmap *list,
   return 0;
 }
 
+/*
+ * Find the first (lowest address) zone of a specific type and of
+ * a certain minimum size, with an optional starting address.
+ * The input values of start and len are used as minima.
+ */
+int syslinux_memmap_find(struct syslinux_memmap *list,
+                        enum syslinux_memmap_types type,
+                        addr_t *start, addr_t *len, addr_t align)
+{
+  addr_t min_start = *start;
+  addr_t min_len = *len;
+
+  while (list->type != SMT_END) {
+    if (list->type == type) {
+      addr_t xstart, xlen;
+      xstart = min_start > list->start ? min_start : list->start;
+      xstart = ALIGN_UP(xstart, align);
+
+      if (xstart < list->next->start) {
+       xlen = list->next->start - xstart;
+       if (xlen >= min_len) {
+         *start = xstart;
+         *len = xlen;
+         return 0;
+       }
+      }
+    }
+    list = list->next;
+  }
+
+  return -1;                   /* Not found */
+}
+
 /*
  * Free a zonelist.
  */
diff --git a/com32/mboot/Makefile b/com32/mboot/Makefile
new file mode 100644 (file)
index 0000000..64c1d07
--- /dev/null
@@ -0,0 +1,46 @@
+## -----------------------------------------------------------------------
+##
+##   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
+##   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+##
+##   This program is free software; you can redistribute it and/or modify
+##   it under the terms of the GNU General Public License as published by
+##   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+##   Boston MA 02110-1301, USA; either version 2 of the License, or
+##   (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+##
+## Multiboot module
+##
+
+topdir = ../..
+include ../MCONFIG
+
+LIBS      = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC)
+LNXLIBS           = ../libutil/libutil_lnx.a
+
+MODULES          = mboot.c32
+TESTFILES =
+
+OBJS = mboot.o map.o mem.o apm.o
+
+all: $(MODULES) $(TESTFILES)
+
+mboot.elf : $(OBJS) $(LIBS) $(C_LIBS)
+       $(LD) $(LDFLAGS) -o $@ $^
+
+tidy dist:
+       rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp
+
+clean: tidy
+       rm -f *.lnx
+
+spotless: clean
+       rm -f *.lss *.c32 *.com
+       rm -f *~ \#*
+
+install:
+
+-include .*.d
diff --git a/com32/mboot/apm.c b/com32/mboot/apm.c
new file mode 100644 (file)
index 0000000..2cfb7de
--- /dev/null
@@ -0,0 +1,87 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ *   Based on code from the Linux kernel:
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   Original APM BIOS checking by Stephen Rothwell, May 1994
+ *   (sfr@canb.auug.org.au)
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+
+/*
+ * apm.c
+ *
+ * APM information for Multiboot
+ */
+
+#include "mboot.h"
+#include <com32.h>
+
+void mboot_apm(void)
+{
+  static struct apm_info apm;
+  com32sys_t ireg, oreg;
+
+  memset(&ireg, 0, sizeof ireg);
+
+  ireg.eax.w[0] = 0x5300;
+  __intcall(0x15, &ireg, &oreg);
+
+  if (oreg.eflags.l & EFLAGS_CF)
+    return;                    /* No APM BIOS */
+
+  if (oreg.ebx.w[0] != 0x504d)
+    return;                    /* No "PM" signature */
+
+  if (!(oreg.ecx.w[0] & 0x02))
+    return;                    /* 32 bits not supported */
+
+  /* Disconnect first, just in case */
+  ireg.eax.b[0] = 0x04;
+  __intcall(0x15, &ireg, &oreg);
+
+  /* 32-bit connect */
+  ireg.eax.b[0] = 0x03;
+  __intcall(0x15, &ireg, &oreg);
+
+  apm.cseg        = oreg.eax.w[0];
+  apm.offset      = oreg.ebx.l;
+  apm.cseg_16     = oreg.ecx.w[0];
+  apm.dseg_16     = oreg.edx.w[0];
+  apm.cseg_len    = oreg.esi.w[0];
+  apm.cseg_16_len = oreg.esi.w[1];
+  apm.dseg_16_len = oreg.edi.w[0];
+
+  /* Redo the installation check as the 32-bit connect;
+     some BIOSes return different flags this way... */
+
+  ireg.eax.b[0] = 0x00;
+  __intcall(0x15, &ireg, &oreg);
+
+  if ((oreg.eflags.l & EFLAGS_CF) || (oreg.ebx.w[0] != 0x504d)) {
+    /* Failure with 32-bit connect, try to disconect and ignore */
+    ireg.eax.b[0] = 0x04;
+    __intcall(0x15, &ireg, NULL);
+    return;
+  }
+
+  apm.version = oreg.eax.w[0];
+
+  mbinfo.apm_table = map_data(&apm, sizeof apm, 4, false);
+  if (mbinfo.apm_table)
+    mbinfo.flags |= MB_INFO_APM_TABLE;
+}
diff --git a/com32/mboot/map.c b/com32/mboot/map.c
new file mode 100644 (file)
index 0000000..b134a55
--- /dev/null
@@ -0,0 +1,330 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * map.c
+ *
+ * Functions that deal with the memory map of various objects
+ */
+
+#include "mboot.h"
+
+static struct syslinux_movelist *ml = NULL;
+static struct syslinux_memmap *mmap = NULL, *amap = NULL;
+static struct multiboot_header *mbh;
+static addr_t mboot_high_water_mark = 0x100000;
+
+/*
+ * Note: although there is no such thing in the spec, at least Xen makes
+ * assumptions as to where in the memory space Grub would have loaded
+ * certain things.  To support that, if "high" is set, then allocate this
+ * at an address strictly above any previous allocations.
+ *
+ * As a precaution, this also pads the data with zero up to the next
+ * alignment datum.
+ */
+addr_t map_data(const void *data, size_t len, size_t align, int flags)
+{
+  addr_t start = (flags & MAP_HIGH) ? mboot_high_water_mark : 0x2000;
+  addr_t pad   = (flags & MAP_NOPAD) ? 0 : -len & (align-1);
+  addr_t xlen  = len+pad;
+
+  if (syslinux_memmap_find(amap, SMT_FREE, &start, &xlen, align) ||
+      syslinux_add_memmap(&amap, start, len+pad, SMT_ALLOC) ||
+      syslinux_add_movelist(&ml, start, (addr_t)data, len) ||
+      (pad && syslinux_add_memmap(&mmap, start+len, pad, SMT_ZERO))) {
+    printf("Cannot map %zu bytes\n", len+pad);
+    return 0;
+  }
+
+  dprintf("Mapping 0x%08x bytes (%#x pad) at 0x%08x\n", len, pad, start);
+
+  if (start+len+pad > mboot_high_water_mark)
+    mboot_high_water_mark = start+len+pad;
+
+  return start;
+}
+
+addr_t map_string(const char *string)
+{
+  if (!string)
+    return 0;
+  else
+    return map_data(string, strlen(string)+1, 1, 0);
+}
+
+int map_image(void *ptr, size_t len)
+{
+  int mbh_len;
+  char *cptr = ptr;
+  Elf32_Ehdr *eh = ptr;
+  Elf32_Phdr *ph;
+  Elf32_Shdr *sh;
+  unsigned int i;
+  uint32_t bad_flags;
+
+  regs.eax = MULTIBOOT_VALID;
+
+  /*
+   * Search for the multiboot header...
+   */
+  mbh_len = 0;
+  for (i = 0 ; i < MULTIBOOT_SEARCH ; i += 4) {
+    mbh = (struct multiboot_header *)((char *)ptr + i);
+    if (mbh->magic != MULTIBOOT_MAGIC)
+      continue;
+    if (mbh->magic + mbh->flags + mbh->checksum)
+      continue;
+    if (mbh->flags & MULTIBOOT_VIDEO_MODE)
+      mbh_len = 48;
+    else if (mbh->flags & MULTIBOOT_AOUT_KLUDGE)
+      mbh_len = 32;
+    else
+      mbh_len = 12;
+
+    if (i + mbh_len < len)
+      mbh_len = 0;             /* Invalid... */
+    else
+      break;                   /* Found something... */
+  }
+
+  if (mbh_len) {
+    bad_flags = mbh->flags & (MULTIBOOT_UNSUPPORTED|MULTIBOOT_VIDEO_MODE);
+    if (bad_flags) {
+      printf("Unsupported Multiboot flags set: %#x\n", bad_flags);
+      return -1;
+    }
+  }
+
+  /*
+   * Note: mmap is the memory map (containing free and zeroed regions)
+   * needed by syslinux_shuffle_boot_pm(); amap is a map where we keep
+   * track ourselves which target memory ranges have already been
+   * allocated.
+   */
+  if ( len < sizeof(Elf32_Ehdr) ||
+       memcmp(eh->e_ident, "\x7f""ELF\1\1\1", 6) ||
+       (eh->e_machine != EM_386 && eh->e_machine != EM_486 &&
+       eh->e_machine != EM_X86_64) ||
+       eh->e_version != EV_CURRENT ||
+       eh->e_ehsize < sizeof(Elf32_Ehdr) || eh->e_ehsize >= len ||
+       eh->e_phentsize < sizeof(Elf32_Phdr) ||
+       !eh->e_phnum ||
+       eh->e_phoff+eh->e_phentsize*eh->e_phnum > len )
+    eh = NULL;                 /* No valid ELF header found */
+
+  mmap = syslinux_memory_map();
+  amap = syslinux_dup_memmap(mmap);
+  if (!mmap || !amap) {
+    error("Failed to allocate initial memory map!\n");
+    goto bail;
+  }
+
+#if DEBUG
+  dprintf("Initial memory map:\n");
+  syslinux_dump_memmap(stdout, mmap);
+#endif
+
+  /*
+   * Note: the Multiboot Specification implies that AOUT_KLUDGE should
+   * have precedence over the ELF header.  However, Grub disagrees, and
+   * Grub is "the reference bootloader" for the Multiboot Specification.
+   * This is insane, since it makes the AOUT_KLUDGE bit functionally
+   * useless, but at least Solaris apparently depends on this behavior.
+   */
+  if (eh) {
+    regs.eip = eh->e_entry;
+
+    ph = (Elf32_Phdr *)(cptr+eh->e_phoff);
+
+    for (i = 0; i < eh->e_phnum; i++) {
+      if (ph->p_type == PT_LOAD || ph->p_type == PT_PHDR) {
+       /* This loads at p_paddr, which is arguably the correct semantics.
+          The SysV spec says that SysV loads at p_vaddr (and thus Linux does,
+          too); that is, however, a major brainfuckage in the spec. */
+       addr_t addr  = ph->p_paddr;
+       addr_t msize = ph->p_memsz;
+       addr_t dsize = min(msize, ph->p_filesz);
+
+       dprintf("Segment at 0x%08x data 0x%08x len 0x%08x\n",
+               addr, dsize, msize);
+
+       if (syslinux_memmap_type(amap, addr, msize) != SMT_FREE) {
+         printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
+                addr, msize);
+         goto bail;            /* Memory region unavailable */
+       }
+
+       /* Mark this region as allocated in the available map */
+       if (syslinux_add_memmap(&amap, addr, msize, SMT_ALLOC)) {
+         error("Overlapping segments found in ELF header\n");
+         goto bail;
+       }
+
+       if (ph->p_filesz) {
+         /* Data present region.  Create a move entry for it. */
+         if (syslinux_add_movelist(&ml, addr, (addr_t)cptr+ph->p_offset,
+                                   dsize)) {
+           error("Failed to map PHDR data\n");
+           goto bail;
+         }
+       }
+       if (msize > dsize) {
+         /* Zero-filled region.  Mark as a zero region in the memory map. */
+         if (syslinux_add_memmap(&mmap, addr+dsize, msize-dsize, SMT_ZERO)) {
+           error("Failed to map PHDR zero region\n");
+           goto bail;
+         }
+       }
+       if (addr+msize > mboot_high_water_mark)
+         mboot_high_water_mark = addr+msize;
+      } else {
+       /* Ignore this program header */
+      }
+
+      ph = (Elf32_Phdr *)((char *)ph + eh->e_phentsize);
+    }
+
+    /* Load the ELF symbol table */
+    if (eh->e_shoff) {
+      addr_t addr, len;
+
+      sh = (Elf32_Shdr *)((char *)eh + eh->e_shoff);
+
+      len = eh->e_shentsize * eh->e_shnum;
+      /*
+       * Align this, but don't pad -- in general this means a bunch of
+       * smaller sections gets packed into a single page.
+       */
+      addr = map_data(sh, len, 4096, MAP_HIGH|MAP_NOPAD);
+      if (!addr) {
+       error("Failed to map symbol table\n");
+       goto bail;
+      }
+
+      mbinfo.flags |= MB_INFO_ELF_SHDR;
+      mbinfo.syms.e.addr  = addr;
+      mbinfo.syms.e.num   = eh->e_shnum;
+      mbinfo.syms.e.size  = eh->e_shentsize;
+      mbinfo.syms.e.shndx = eh->e_shstrndx;
+
+      for (i = 0; i < eh->e_shnum; i++) {
+       addr_t align;
+
+       if (!sh[i].sh_size)
+         continue;             /* Empty section */
+       if (sh[i].sh_flags & SHF_ALLOC)
+         continue;             /* SHF_ALLOC sections should have PHDRs */
+
+       align = sh[i].sh_addralign ? sh[i].sh_addralign : 0;
+       addr = map_data((char *)ptr + sh[i].sh_offset, sh[i].sh_size,
+                       align, MAP_HIGH);
+       if (!addr) {
+         error("Failed to map symbol section\n");
+         goto bail;
+       }
+       sh[i].sh_addr = addr;
+      }
+    }
+  } else if (mbh_len && (mbh->flags & MULTIBOOT_AOUT_KLUDGE)) {
+    /*
+     * a.out kludge thing...
+     */
+    char *data_ptr;
+    addr_t data_len, bss_len;
+
+    regs.eip = mbh->entry_addr;
+
+    data_ptr = (char *)mbh - (mbh->header_addr - mbh->load_addr);
+    data_len = mbh->load_end_addr - mbh->load_addr;
+    bss_len  = mbh->bss_end_addr - mbh->load_end_addr;
+
+    if (syslinux_memmap_type(amap, mbh->load_addr, data_len+bss_len)
+       != SMT_FREE) {
+      printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
+            mbh->load_addr, data_len+bss_len);
+      goto bail;               /* Memory region unavailable */
+    }
+    if (syslinux_add_memmap(&amap, mbh->load_addr,
+                           data_len+bss_len, SMT_ALLOC)) {
+      error("Failed to claim a.out address space!\n");
+      goto bail;
+    }
+    if (data_len)
+      if (syslinux_add_movelist(&ml, mbh->load_addr, (addr_t)data_ptr,
+                               data_len)) {
+       error("Failed to map a.out data\n");
+       goto bail;
+      }
+    if (bss_len)
+      if (syslinux_add_memmap(&mmap, mbh->load_end_addr, bss_len, SMT_ZERO)) {
+       error("Failed to map a.out bss\n");
+       goto bail;
+      }
+    if (mbh->bss_end_addr > mboot_high_water_mark)
+      mboot_high_water_mark = mbh->bss_end_addr;
+  } else {
+    error("Invalid Multiboot image: neither ELF header nor a.out kludge found\n");
+    goto bail;
+  }
+
+  return 0;
+
+ bail:
+  syslinux_free_memmap(amap);
+  syslinux_free_memmap(mmap);
+  syslinux_free_movelist(ml);
+  return -1;
+}
+
+/*
+ * Set up a stack.  This isn't actually required by the spec, but it seems
+ * like a prudent thing to do.  Also, put enough zeros at the top of the
+ * stack that something that looks for an ELF invocation record will know
+ * there isn't one.
+ */
+static void mboot_map_stack(void)
+{
+  addr_t start, len;
+
+  if (syslinux_memmap_largest(amap, SMT_FREE, &start, &len) || len < 64)
+    return;                    /* Not much we can do, here... */
+
+  regs.esp = (start+len-32) & ~7;
+  dprintf("Mapping stack at 0x%08x\n", regs.esp);
+  syslinux_add_memmap(&mmap, regs.esp, 32, SMT_ZERO);
+}
+
+void mboot_run(int bootflags)
+{
+  mboot_map_stack();
+  
+  dprintf("Running, eip = 0x%08x, ebx = 0x%08x\n", regs.eip, regs.ebx);
+
+  syslinux_shuffle_boot_pm(ml, mmap, bootflags, &regs);
+}
similarity index 71%
rename from com32/modules/mb_info.h
rename to com32/mboot/mb_info.h
index 91a1392..ec12fe8 100644 (file)
  *  The structure type "mod_list" is used by the "multiboot_info" structure.
  */
 
+#include <inttypes.h>
+
 struct mod_list
 {
   /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
-  unsigned long mod_start;
-  unsigned long mod_end;
+  uint32_t mod_start;
+  uint32_t mod_end;
 
   /* Module command line */
-  unsigned long cmdline;
+  uint32_t cmdline;
 
   /* padding to take it to 16 bytes (must be zero) */
-  unsigned long pad;
+  uint32_t pad;
 };
 
 
@@ -44,13 +46,13 @@ struct mod_list
 
 struct AddrRangeDesc
 {
-  unsigned long size;
-  unsigned long long BaseAddr;
-  unsigned long long Length;
-  unsigned long Type;
+  uint32_t size;
+  uint64_t BaseAddr;
+  uint64_t Length;
+  uint32_t Type;
 
   /* unspecified optional padding... */
-};
+} __attribute__((packed));
 
 /* usable memory "Type", all others are reserved.  */
 #define MB_ARD_MEMORY          1
@@ -60,21 +62,21 @@ struct AddrRangeDesc
 struct drive_info
 {
   /* The size of this structure.  */
-  unsigned long size;
+  uint32_t size;
 
   /* The BIOS drive number.  */
-  unsigned char drive_number;
+  uint8_t  drive_number;
 
   /* The access mode (see below).  */
-  unsigned char drive_mode;
+  uint8_t  drive_mode;
 
   /* The BIOS geometry.  */
-  unsigned short drive_cylinders;
-  unsigned char drive_heads;
-  unsigned char drive_sectors;
+  uint16_t drive_cylinders;
+  uint8_t  drive_heads;
+  uint8_t  drive_sectors;
 
   /* The array of I/O ports used for the drive.  */
-  unsigned short drive_ports[0];
+  uint16_t drive_ports[0];
 };
 
 /* Drive Mode.  */
@@ -85,14 +87,14 @@ struct drive_info
 /* APM BIOS info.  */
 struct apm_info
 {
-  unsigned short version;
-  unsigned short cseg;
-  unsigned long offset;
-  unsigned short cseg_16;
-  unsigned short dseg_16;
-  unsigned short cseg_len;
-  unsigned short cseg_16_len;
-  unsigned short dseg_16_len;
+  uint16_t version;
+  uint16_t cseg;
+  uint32_t offset;
+  uint16_t cseg_16;
+  uint16_t dseg_16;
+  uint16_t cseg_len;
+  uint16_t cseg_16_len;
+  uint16_t dseg_16_len;
 };
 
 
@@ -106,70 +108,70 @@ struct apm_info
 struct multiboot_info
 {
   /* MultiBoot info version number */
-  unsigned long flags;
+  uint32_t flags;
 
   /* Available memory from BIOS */
-  unsigned long mem_lower;
-  unsigned long mem_upper;
+  uint32_t mem_lower;
+  uint32_t mem_upper;
 
   /* "root" partition */
-  unsigned long boot_device;
+  uint32_t boot_device;
 
   /* Kernel command line */
-  unsigned long cmdline;
+  uint32_t cmdline;
 
   /* Boot-Module list */
-  unsigned long mods_count;
-  unsigned long mods_addr;
+  uint32_t mods_count;
+  uint32_t mods_addr;
 
   union
   {
     struct
     {
       /* (a.out) Kernel symbol table info */
-      unsigned long tabsize;
-      unsigned long strsize;
-      unsigned long addr;
-      unsigned long pad;
+      uint32_t tabsize;
+      uint32_t strsize;
+      uint32_t addr;
+      uint32_t pad;
     }
     a;
 
     struct
     {
       /* (ELF) Kernel section header table */
-      unsigned long num;
-      unsigned long size;
-      unsigned long addr;
-      unsigned long shndx;
+      uint32_t num;
+      uint32_t size;
+      uint32_t addr;
+      uint32_t shndx;
     }
     e;
   }
   syms;
 
   /* Memory Mapping buffer */
-  unsigned long mmap_length;
-  unsigned long mmap_addr;
+  uint32_t mmap_length;
+  uint32_t mmap_addr;
 
   /* Drive Info buffer */
-  unsigned long drives_length;
-  unsigned long drives_addr;
+  uint32_t drives_length;
+  uint32_t drives_addr;
 
   /* ROM configuration table */
-  unsigned long config_table;
+  uint32_t config_table;
 
   /* Boot Loader Name */
-  unsigned long boot_loader_name;
+  uint32_t boot_loader_name;
 
   /* APM table */
-  unsigned long apm_table;
+  uint32_t apm_table;
 
   /* Video */
-  unsigned long vbe_control_info;
-  unsigned long vbe_mode_info;
-  unsigned short vbe_mode;
-  unsigned short vbe_interface_seg;
-  unsigned short vbe_interface_off;
-  unsigned short vbe_interface_len;
+  uint32_t vbe_control_info;
+  uint32_t vbe_mode_info;
+  uint16_t vbe_mode;
+  uint16_t vbe_interface_seg;
+  uint16_t vbe_interface_off;
+  uint16_t vbe_interface_len;
 };
 
 /*
diff --git a/com32/mboot/mboot.c b/com32/mboot/mboot.c
new file mode 100644 (file)
index 0000000..3b42093
--- /dev/null
@@ -0,0 +1,203 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mboot.c
+ *
+ * Module to load a multiboot kernel
+ */
+
+#include "mboot.h"
+
+struct multiboot_info mbinfo;
+struct syslinux_pm_regs regs;
+
+struct module_data {
+  void *data;
+  size_t len;
+  const char *cmdline;
+};
+
+static int map_modules(struct module_data *modules, int nmodules)
+{
+  struct mod_list *mod_list;
+  addr_t map_list = 0;
+  size_t list_size = nmodules * sizeof *mod_list;
+  int i;
+
+  mod_list = malloc(list_size);
+  if (!mod_list) {
+    printf("Failed to allocate module list\n");
+    return -1;
+  }
+
+  map_list = map_data(mod_list, list_size, 16, 0);
+  if (!map_list) {
+    printf("Cannot map module list\n");
+    return -1;
+  }
+
+  for (i = 0; i < nmodules; i++) {
+    addr_t mod_map = 0;
+    addr_t cmd_map = 0;
+
+    dprintf("Module %d cmdline: \"%s\"\n", i, modules[i].cmdline);
+
+    cmd_map = map_string(modules[i].cmdline);
+
+    mod_map = map_data(modules[i].data, modules[i].len, 4096, MAP_HIGH);
+    if (!mod_map) {
+      printf("Failed to map module (memory fragmentation issue?)\n");
+      return -1;
+    }
+    mod_list[i].mod_start = mod_map;
+    mod_list[i].mod_end = mod_map + modules[i].len;
+    mod_list[i].cmdline = cmd_map;
+    mod_list[i].pad = 0;
+  }
+
+  mbinfo.flags |= MB_INFO_MODS;
+  mbinfo.mods_count = nmodules;
+  mbinfo.mods_addr = map_list;
+  return 0;
+}
+
+static int get_modules(char **argv, struct module_data **mdp)
+{
+  char **argp, **argx;
+  struct module_data *mp;
+  int rv;
+  int module_count = 1;
+  int arglen;
+  const char module_separator[] = "---";
+
+  for (argp = argv; *argp; argp++) {
+    if (!strcmp(*argp, module_separator))
+      module_count++;
+  }
+
+  *mdp = mp = malloc(module_count * sizeof(struct module_data));
+  if (!mp) {
+    error("Out of memory!\n");
+    return -1;
+  }
+
+  argp = argv;
+  while (*argp) {
+    /* Note: it seems Grub transparently decompresses all compressed files,
+       not just the primary kernel. */
+    printf("Loading %s... ", *argp);
+    rv = zloadfile(*argp, &mp->data, &mp->len);
+
+    if (rv) {
+      printf("failed!\n");
+      return -1;
+    }
+    printf("ok\n");
+
+    argp++;
+    arglen = 0;
+    for (argx = argp; *argx && strcmp(*argx, module_separator); argx++)
+      arglen += strlen(*argx)+1;
+
+    if (arglen == 0) {
+      mp->cmdline = strdup("");
+    } else {
+      char *p;
+      mp->cmdline = p = malloc(arglen);
+      for ( ; *argp && strcmp(*argp, module_separator); argp++) {
+       p = strpcpy(p, *argp);
+       *p++ = ' ';
+      }
+      *--p = '\0';
+    }
+    mp++;
+    if (*argp)
+      argp++;                  /* Advance past module_separator */
+  }
+
+  return module_count;
+}
+
+int main(int argc, char *argv[])
+{
+  int nmodules;
+  struct module_data *modules;
+  bool keeppxe = false;
+
+  openconsole(&dev_null_r, &dev_stdcon_w);
+
+  if (argc < 2) {
+    error("Usage: mboot.c32 mboot_file args... [--- module args...]...\n");
+    return 1;
+  }
+
+  /* Load the files */
+  nmodules = get_modules(argv+1, &modules);
+  if (nmodules < 1) {
+    error("No modules found!\n");
+    return 1;                  /* Failure */
+  }
+
+  /*
+   * Map the primary image.  This should be done before mapping anything
+   * else, since it will have fixed address requirements.
+   */
+  if (map_image(modules[0].data, modules[0].len))
+    return 1;
+
+  /* Map the mbinfo structure */
+  regs.ebx = map_data(&mbinfo, sizeof mbinfo, 4, 0);
+  if (!regs.ebx) {
+    error("Failed to map Multiboot info structure!\n");
+    return 1;
+  }
+
+  /* Map the primary command line */
+  if (modules[0].cmdline) {
+    mbinfo.cmdline = map_string(modules[0].cmdline);
+    dprintf("Main cmdline: \"%s\"\n", modules[0].cmdline);
+    if (mbinfo.cmdline)
+      mbinfo.flags |= MB_INFO_CMDLINE;
+  }
+
+  /* Map auxilliary images */
+  if (nmodules > 1) {
+    if (map_modules(modules+1, nmodules-1))
+      return 1;
+  }
+
+  /* Add auxilliary information */
+  mboot_make_memmap();
+  mboot_apm();
+
+  /* Run it */
+  mboot_run(keeppxe ? 3 : 0);
+  error("mboot.c32: boot failed\n");
+  return 1;
+}
diff --git a/com32/mboot/mboot.h b/com32/mboot/mboot.h
new file mode 100644 (file)
index 0000000..0f33a51
--- /dev/null
@@ -0,0 +1,87 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 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
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mboot.h
+ *
+ * Module to load a multiboot kernel
+ */
+
+#ifndef MBOOT_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <minmax.h>
+#include <sys/stat.h>
+#include <elf.h>
+#include <console.h>
+
+#include <syslinux/loadfile.h>
+#include <syslinux/movebits.h>
+#include <syslinux/bootpm.h>
+
+#include "mb_header.h"
+#include "mb_info.h"
+
+#define DEBUG 0
+#if DEBUG
+# define dprintf printf
+#else
+# define dprintf(f, ...) ((void)0)
+#endif
+
+static inline void error(const char *msg)
+{
+  fputs(msg, stderr);
+}
+
+/* mboot.c */
+extern struct multiboot_info mbinfo;
+extern struct syslinux_pm_regs regs;
+
+/* map.c */
+#define MAP_HIGH       1
+#define MAP_NOPAD      2
+addr_t map_data(const void *data, size_t len, size_t align, int flags);
+addr_t map_string(const char *string);
+int map_image(void *ptr, size_t len);
+void mboot_run(int bootflags);
+
+/* mem.c */
+void mboot_make_memmap(void);
+
+/* apm.c */
+void mboot_apm(void);
+
+#endif /* MBOOT_H */
diff --git a/com32/mboot/mem.c b/com32/mboot/mem.c
new file mode 100644 (file)
index 0000000..e9d8bbd
--- /dev/null
@@ -0,0 +1,215 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mem.c
+ *
+ * Obtain a memory map for a Multiboot OS
+ *
+ * This differs from the libcom32 memory map functions in that it doesn't
+ * attempt to filter out memory regions...
+ */
+
+#include "mboot.h"
+#include <com32.h>
+
+struct e820_entry {
+  uint64_t start;
+  uint64_t len;
+  uint32_t type;
+  uint32_t extattr;
+};
+
+#define RANGE_ALLOC_BLOCK      128
+
+static int mboot_scan_memory(struct AddrRangeDesc **ardp, uint32_t *dosmem)
+{
+  com32sys_t ireg, oreg;
+  struct e820_entry *e820buf = __com32.cs_bounce;
+  struct AddrRangeDesc *ard;
+  size_t ard_count, ard_space;
+
+  /* Use INT 12h to get DOS memory */
+  __intcall(0x12, &__com32_zero_regs, &oreg);
+  *dosmem = oreg.eax.w[0] << 10;
+  if (*dosmem < 32*1024 || *dosmem > 640*1024) {
+    /* INT 12h reports nonsense... now what? */
+    uint16_t ebda_seg = *(uint16_t *)0x40e;
+    if (ebda_seg >= 0x8000 && ebda_seg < 0xa000)
+      *dosmem = ebda_seg << 4;
+    else
+      *dosmem = 640*1024;      /* Hope for the best... */
+  }
+
+  /* Allocate initial space */
+  *ardp = ard = malloc(RANGE_ALLOC_BLOCK * sizeof *ard);
+  if (!ard)
+    return 0;
+
+  ard_count = 0;
+  ard_space = RANGE_ALLOC_BLOCK;
+
+  /* First try INT 15h AX=E820h */
+  memset(&ireg, 0, sizeof ireg);
+  ireg.eax.l    = 0xe820;
+  ireg.edx.l    = 0x534d4150;
+  /* ireg.ebx.l    = 0; */
+  ireg.ecx.l    = sizeof(*e820buf);
+  ireg.es       = SEG(e820buf);
+  ireg.edi.w[0] = OFFS(e820buf);
+  memset(e820buf, 0, sizeof *e820buf);
+  /* Set this in case the BIOS doesn't, but doesn't change %ecx to match. */
+  e820buf->extattr = 1;
+
+  do {
+    __intcall(0x15, &ireg, &oreg);
+
+    if ((oreg.eflags.l & EFLAGS_CF) ||
+       (oreg.eax.l != 0x534d4150) ||
+       (oreg.ecx.l < 20))
+      break;
+
+    if (oreg.ecx.l < 24)
+      e820buf->extattr = 1;    /* Enabled, normal */
+
+    if (!(e820buf->extattr & 1))
+      continue;
+
+    if (ard_count >= ard_space) {
+      ard_space += RANGE_ALLOC_BLOCK;
+      *ardp = ard = realloc(ard, ard_space*sizeof *ard);
+      if (!ard)
+       return ard_count;
+    }
+
+    ard[ard_count].size     = 20;
+    ard[ard_count].BaseAddr = e820buf->start;
+    ard[ard_count].Length   = e820buf->len;
+    ard[ard_count].Type     = e820buf->type;
+    ard_count++;
+
+    ireg.ebx.l = oreg.ebx.l;
+  } while (oreg.ebx.l);
+
+  if (ard_count)
+    return ard_count;
+
+  ard[0].size = 20;
+  ard[0].BaseAddr = 0;
+  ard[0].Length = *dosmem << 10;
+  ard[0].Type = 1;
+
+  /* Next try INT 15h AX=E801h */
+  ireg.eax.w[0] = 0xe801;
+  __intcall(0x15, &ireg, &oreg);
+
+  if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) {
+    ard[1].size = 20;
+    ard[1].BaseAddr = 1 << 20;
+    ard[1].Length = oreg.ecx.w[0] << 10;
+    ard[1].Type = 1;
+
+    if (oreg.edx.w[0]) {
+      ard[2].size = 20;
+      ard[2].BaseAddr = 16 << 20;
+      ard[2].Length = oreg.edx.w[0] << 16;
+      ard[2].Type = 1;
+      return 3;
+    } else {
+      return 2;
+    }
+  }
+
+  /* Finally try INT 15h AH=88h */
+  ireg.eax.w[0] = 0x8800;
+  if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) {
+    ard[1].size = 20;
+    ard[1].BaseAddr = 1 << 20;
+    ard[1].Length = oreg.ecx.w[0] << 10;
+    ard[1].Type = 1;
+    return 2;
+  }
+
+  return 1;                    /* ... problematic ... */
+}
+
+void mboot_make_memmap(void)
+{
+  int i, nmap;
+  struct AddrRangeDesc *ard;
+  uint32_t lowmem, highmem;
+  uint32_t highrsvd;
+
+  /* Always report DOS memory as "lowmem", this may be overly conservative
+     (e.g. if we're dropping PXE), but it should be *safe*... */
+
+  nmap = mboot_scan_memory(&ard, &lowmem);
+
+  highmem  = 0x100000;
+  highrsvd = 0xfff00000;
+
+ again:
+  for (i = 0; i < nmap; i++) {
+    uint64_t start, end;
+
+    start = ard[i].BaseAddr;
+    end = start + ard[i].Length;
+
+    if (end < start)
+      end = ~0ULL;
+
+    if (start & 0xffffffff00000000ULL)
+      continue;                        /* Not interested in 64-bit memory */
+
+    if (start < highmem)
+      start = highmem;
+
+    if (end <= start)
+      continue;
+
+    if (ard[i].Type == 1 && start == highmem) {
+      highmem = end;
+      goto again;
+    } else if (ard[i].Type != 1 && start < highrsvd)
+      highrsvd = start;
+  }
+
+  if (highmem > highrsvd)
+    highmem = highrsvd;
+
+  mbinfo.mem_lower = lowmem >> 10;
+  mbinfo.mem_upper = (highmem - 0x100000) >> 10;
+  mbinfo.flags |= MB_INFO_MEMORY;
+
+  /* The spec says this address should be +4, but Grub disagrees */
+  mbinfo.mmap_addr = map_data(ard, nmap*sizeof *ard, 4, false);
+  if (mbinfo.mmap_addr) {
+    mbinfo.mmap_length = nmap*sizeof *ard;
+    mbinfo.flags |= MB_INFO_MEM_MAP;
+  }
+}
index 428d970..ace0451 100644 (file)
@@ -9,7 +9,7 @@ void drain_keyboard(void)
   /* Prevent "ghost typing" and keyboard buffer snooping */
   volatile char junk;
   int rv;
-  
+
   do {
     rv = read(0, (char *)&junk, 1);
   } while (rv > 0);
@@ -23,5 +23,3 @@ void drain_keyboard(void)
   memset((void *)0x41e, 0, 32); /* Clear the actual keyboard buffer */
   sti();
 }
-
-  
index ace0e57..d84958c 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------- *
- *   
+ *
  *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -67,4 +67,3 @@ void execute(const char *cmdline, enum kernel_type type)
 
   /* If this returns, something went bad; return to menu */
 }
-
index f008963..e3155bd 100644 (file)
 topdir = ../..
 include ../MCONFIG
 
-MODULES          = chain.c32 config.c32 ethersel.c32 mboot.c32 dmitest.c32 \
-           cpuidtest.c32 \
+MODULES          = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
            pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \
-           sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32
+           sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \
+           vpdtest.c32
 
 TESTFILES =
 
index 979ede2..ead908f 100644 (file)
@@ -1,6 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -446,79 +447,15 @@ static void do_boot(void *boot_sector, size_t boot_size,
     return;
   }
 
-  if (loadbase < 0x7c00) {
-    /* Special hack: if we are to be loaded below 0x7c00, we need to handle
-       the part that goes below 0x7c00 specially, since that's where the
-       shuffler lives.  To deal with that, stuff the balance at the end
-       of low memory and put a small copy stub there.
-
-       The only tricky bit is that we need to set up registers for our
-       move, and then restore them to what they should be at the end of
-       the code. */
-    static uint8_t copy_down_code[] = {
-      0xf3,0x66,0xa5,          /* 00: rep movsd */
-      0xbe,0,0,                        /* 03: mov si,0 */
-      0xbf,0,0,                        /* 06: mov di,0 */
-      0x8e,0xde,               /* 09: mov ds,si */
-      0x8e,0xc7,               /* 0b: mov es,di */
-      0x66,0xb9,0,0,0,0,       /* 0d: mov ecx,0 */
-      0x66,0xbe,0,0,0,0,       /* 13: mov esi,0 */
-      0x66,0xbf,0,0,0,0,       /* 19: mov edi,0 */
-      0xea,0,0,0,0,            /* 1f: jmp 0:0 */
-      /* pad out to segment boundary */
-      0x90,0x90,0x90,0x90,     /* 24: ... */
-      0x90,0x90,0x90,0x90,     /* 28: ... */
-      0x90,0x90,0x90,0x90,     /* 2c: ... */
-    };
-    size_t low_size  = min(boot_size, 0x7c00-loadbase);
-    size_t high_size = boot_size - low_size;
-    size_t low_addr  = (0x7c00 + high_size + 15) & ~15;
-    size_t move_addr = (low_addr + low_size + 15) & ~15;
-    const size_t move_size = sizeof copy_down_code;
-
-    if (move_addr+move_size >= dosmem-0x7c00)
-      goto too_big;
-
-    *(uint16_t *)&copy_down_code[0x04] = regs->ds;
-    *(uint16_t *)&copy_down_code[0x07] = regs->es;
-    *(uint32_t *)&copy_down_code[0x0f] = regs->ecx.l;
-    *(uint32_t *)&copy_down_code[0x15] = regs->esi.l;
-    *(uint32_t *)&copy_down_code[0x1b] = regs->edi.l;
-    *(uint16_t *)&copy_down_code[0x20] = regs->ip;
-    *(uint16_t *)&copy_down_code[0x22] = regs->cs;
-
-    regs->ecx.l = (low_size+3) >> 2;
-    regs->esi.l = 0;
-    regs->edi.l = loadbase & 15;
-    regs->ds    = low_addr >> 4;
-    regs->es    = loadbase >> 4;
-    regs->cs    = move_addr >> 4;
-    regs->ip    = 0;
-
-    endimage = move_addr + move_size;
-
-    if (high_size)
-      if (syslinux_add_movelist(&mlist, 0x7c00,
-                               (addr_t)boot_sector+low_size, high_size))
-       goto enomem;
-    if (syslinux_add_movelist(&mlist, low_addr,
-                             (addr_t)boot_sector, low_size))
-      goto enomem;
-    if (syslinux_add_movelist(&mlist, move_addr,
-                             (addr_t)copy_down_code, move_size))
-      goto enomem;
-  } else {
-    /* Nothing below 0x7c00, much simpler... */
+  /* Nothing below 0x7c00, much simpler... */
 
-    if (boot_size >= dosmem-0x7c00)
+  if (boot_size >= dosmem - loadbase)
       goto too_big;
 
-    endimage = loadbase + boot_size;
+  endimage = loadbase + boot_size;
 
-    if (syslinux_add_movelist(&mlist, loadbase, (addr_t)boot_sector,
-                             boot_size))
-      goto enomem;
-  }
+  if (syslinux_add_movelist(&mlist, loadbase, (addr_t)boot_sector, boot_size))
+    goto enomem;
 
   if (opt.swap && driveno != swapdrive) {
     static const uint8_t swapstub_master[] = {
diff --git a/com32/modules/i386-elf.h b/com32/modules/i386-elf.h
deleted file mode 100644 (file)
index 04ddf39..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2001,2002  Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  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; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* 32-bit data types */
-
-typedef unsigned long Elf32_Addr;
-typedef unsigned short Elf32_Half;
-typedef unsigned long Elf32_Off;
-typedef signed long Elf32_Sword;
-typedef unsigned long Elf32_Word;
-/* "unsigned char" already exists */
-
-/* ELF header */
-typedef struct
-{
-
-#define EI_NIDENT 16
-
-  /* first four characters are defined below */
-#define EI_MAG0                0
-#define ELFMAG0                0x7f
-#define EI_MAG1                1
-#define ELFMAG1                'E'
-#define EI_MAG2                2
-#define ELFMAG2                'L'
-#define EI_MAG3                3
-#define ELFMAG3                'F'
-
-#define EI_CLASS       4       /* data sizes */
-#define ELFCLASS32     1       /* i386 -- up to 32-bit data sizes present */
-
-#define EI_DATA                5       /* data type and ordering */
-#define ELFDATA2LSB    1       /* i386 -- LSB 2's complement */
-
-#define EI_VERSION     6       /* version number.  "e_version" must be the same */
-#define EV_CURRENT      1      /* current version number */
-
-#define EI_OSABI       7       /* operating system/ABI indication */
-#define ELFOSABI_FREEBSD       9
-
-#define EI_ABIVERSION  8       /* ABI version */
-
-#define EI_PAD         9       /* from here in is just padding */
-
-#define EI_BRAND       8       /* start of OS branding (This is
-                                  obviously illegal against the ELF
-                                  standard.) */
-
-  unsigned char e_ident[EI_NIDENT];    /* basic identification block */
-
-#define ET_EXEC                2       /* we only care about executable types */
-  Elf32_Half e_type;           /* file types */
-
-#define EM_386         3       /* i386 -- obviously use this one */
-  Elf32_Half e_machine;        /* machine types */
-  Elf32_Word e_version;        /* use same as "EI_VERSION" above */
-  Elf32_Addr e_entry;          /* entry point of the program */
-  Elf32_Off e_phoff;           /* program header table file offset */
-  Elf32_Off e_shoff;           /* section header table file offset */
-  Elf32_Word e_flags;          /* flags */
-  Elf32_Half e_ehsize;         /* elf header size in bytes */
-  Elf32_Half e_phentsize;      /* program header entry size */
-  Elf32_Half e_phnum;          /* number of entries in program header */
-  Elf32_Half e_shentsize;      /* section header entry size */
-  Elf32_Half e_shnum;          /* number of entries in section header */
-
-#define SHN_UNDEF       0
-#define SHN_LORESERVE   0xff00
-#define SHN_LOPROC      0xff00
-#define SHN_HIPROC      0xff1f
-#define SHN_ABS         0xfff1
-#define SHN_COMMON      0xfff2
-#define SHN_HIRESERVE   0xffff
-  Elf32_Half e_shstrndx;       /* section header table index */
-}
-Elf32_Ehdr;
-
-
-#define BOOTABLE_I386_ELF(h) \
- ((h.e_ident[EI_MAG0] == ELFMAG0) & (h.e_ident[EI_MAG1] == ELFMAG1) \
-  & (h.e_ident[EI_MAG2] == ELFMAG2) & (h.e_ident[EI_MAG3] == ELFMAG3) \
-  & (h.e_ident[EI_CLASS] == ELFCLASS32) & (h.e_ident[EI_DATA] == ELFDATA2LSB) \
-  & (h.e_ident[EI_VERSION] == EV_CURRENT) & (h.e_type == ET_EXEC) \
-  & (h.e_machine == EM_386) & (h.e_version == EV_CURRENT))
-
-/* section table - ? */
-typedef struct
-{
-  Elf32_Word   sh_name;                /* Section name (string tbl index) */
-  Elf32_Word   sh_type;                /* Section type */
-  Elf32_Word   sh_flags;               /* Section flags */
-  Elf32_Addr   sh_addr;                /* Section virtual addr at execution */
-  Elf32_Off    sh_offset;              /* Section file offset */
-  Elf32_Word   sh_size;                /* Section size in bytes */
-  Elf32_Word   sh_link;                /* Link to another section */
-  Elf32_Word   sh_info;                /* Additional section information */
-  Elf32_Word   sh_addralign;           /* Section alignment */
-  Elf32_Word   sh_entsize;             /* Entry size if section holds table */
-}
-Elf32_Shdr;
-
-/* symbol table - page 4-25, figure 4-15 */
-typedef struct
-{
-  Elf32_Word st_name;
-  Elf32_Addr st_value;
-  Elf32_Word st_size;
-  unsigned char st_info;
-  unsigned char st_other;
-  Elf32_Half st_shndx;
-}
-Elf32_Sym;
-
-/* symbol type and binding attributes - page 4-26 */
-
-#define ELF32_ST_BIND(i)    ((i) >> 4)
-#define ELF32_ST_TYPE(i)    ((i) & 0xf)
-#define ELF32_ST_INFO(b,t)  (((b)<<4)+((t)&0xf))
-
-/* symbol binding - page 4-26, figure 4-16 */
-
-#define STB_LOCAL    0
-#define STB_GLOBAL   1
-#define STB_WEAK     2
-#define STB_LOPROC  13
-#define STB_HIPROC  15
-
-/* symbol types - page 4-28, figure 4-17 */
-
-#define STT_NOTYPE   0
-#define STT_OBJECT   1
-#define STT_FUNC     2
-#define STT_SECTION  3
-#define STT_FILE     4
-#define STT_LOPROC  13
-#define STT_HIPROC  15
-
-
-/* Macros to split/combine relocation type and symbol page 4-32 */
-
-#define ELF32_R_SYM(__i)       ((__i)>>8)
-#define ELF32_R_TYPE(__i)      ((unsigned char) (__i))
-#define ELF32_R_INFO(__s, __t) (((__s)<<8) + (unsigned char) (__t))
-
-
-/* program header - page 5-2, figure 5-1 */
-
-typedef struct
-{
-  Elf32_Word p_type;
-  Elf32_Off p_offset;
-  Elf32_Addr p_vaddr;
-  Elf32_Addr p_paddr;
-  Elf32_Word p_filesz;
-  Elf32_Word p_memsz;
-  Elf32_Word p_flags;
-  Elf32_Word p_align;
-}
-Elf32_Phdr;
-
-/* segment types - page 5-3, figure 5-2 */
-
-#define PT_NULL                0
-#define PT_LOAD                1
-#define PT_DYNAMIC     2
-#define PT_INTERP      3
-#define PT_NOTE                4
-#define PT_SHLIB       5
-#define PT_PHDR                6
-
-#define PT_LOPROC      0x70000000
-#define PT_HIPROC      0x7fffffff
-
-/* segment permissions - page 5-6 */
-
-#define PF_X           0x1
-#define PF_W           0x2
-#define PF_R           0x4
-#define PF_MASKPROC    0xf0000000
-
-
-/* dynamic structure - page 5-15, figure 5-9 */
-
-typedef struct
-{
-  Elf32_Sword d_tag;
-  union
-  {
-    Elf32_Word d_val;
-    Elf32_Addr d_ptr;
-  }
-  d_un;
-}
-Elf32_Dyn;
-
-/* Dynamic array tags - page 5-16, figure 5-10.  */
-
-#define DT_NULL                0
-#define DT_NEEDED      1
-#define DT_PLTRELSZ    2
-#define DT_PLTGOT      3
-#define DT_HASH                4
-#define DT_STRTAB      5
-#define DT_SYMTAB      6
-#define DT_RELA                7
-#define DT_RELASZ      8
-#define DT_RELAENT      9
-#define DT_STRSZ       10
-#define DT_SYMENT      11
-#define DT_INIT                12
-#define DT_FINI                13
-#define DT_SONAME      14
-#define DT_RPATH       15
-#define DT_SYMBOLIC    16
-#define DT_REL         17
-#define DT_RELSZ       18
-#define DT_RELENT      19
-#define DT_PLTREL      20
-#define DT_DEBUG       21
-#define DT_TEXTREL     22
-#define DT_JMPREL      23
diff --git a/com32/modules/mboot.c b/com32/modules/mboot.c
deleted file mode 100644 (file)
index edcb88e..0000000
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
- *  mboot.c
- *
- *  Loader for Multiboot-compliant kernels and modules.
- *
- *  Copyright (C) 2005 Tim Deegan <Tim.Deegan@cl.cam.ac.uk>
- *  Parts based on GNU GRUB, Copyright 2000  Free Software Foundation, Inc.
- *  Parts based on SYSLINUX, Copyright 1994-2008 H. Peter Anvin.
- *  Thanks to Ram Yalamanchili for the ELF section-header loading.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License as
- *  published by the Free Software Foundation; either version 2 of the
- *  License, or (at your option) any later version.
- *
- *  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; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- *  02111-1307, USA.
- *
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <console.h>
-#include <zlib.h>
-#include <com32.h>
-#include <syslinux/pxe.h>
-
-#include "i386-elf.h"
-#include "mb_info.h"
-#include "mb_header.h"
-
-#include <klibc/compiler.h> /* For __constructor */
-
-#define MIN(_x, _y) (((_x)<(_y))?(_x):(_y))
-#define MAX(_x, _y) (((_x)>(_y))?(_x):(_y))
-
-/* Define this for some more printout */
-#undef DEBUG
-
-/* Memory magic numbers */
-#define STACK_SIZE      0x20000      /* XXX Could be much smaller */
-#define MALLOC_SIZE     0x100000     /* XXX Could be much smaller */
-#define MIN_RUN_ADDR    0x10000      /* Lowest address we'll consider using */
-#define MEM_HOLE_START  0xa0000      /* Memory hole runs from 640k ... */
-#define MEM_HOLE_END    0x100000     /* ... to 1MB */
-#define X86_PAGE_SIZE   0x1000
-#define DHCP_ACK_SIZE   2048         /* Maximum size of the DHCP ACK package.
-                                        Probably too large since we're interested
-                                        in the first bunch of bytes only. */
-
-size_t __stack_size = STACK_SIZE;    /* How much stack we'll use */
-extern void *__mem_end;              /* Start of malloc() heap */
-extern char _end[];                  /* End of static data */
-
-/* Pointer to free memory for loading into: load area is between here
- * and section_addr */
-static char *next_load_addr;
-
-/* Memory map for run-time */
-typedef struct section section_t;
-struct section {
-    size_t dest;                     /* Start of run-time allocation */
-    char *src;                       /* Current location of data for memmove(),
-                                      * or NULL for bzero() */
-    size_t size;                     /* Length of allocation */
-};
-static char *section_addr;
-static int section_count;
-
-static size_t max_run_addr;          /* Highest address we'll consider using */
-static size_t next_mod_run_addr;     /* Where the next module will be put */
-
-/* File loads are in units of this much */
-#define LOAD_CHUNK 0x20000
-
-/* Layout of the input to the 32-bit lidt instruction */
-struct lidt_operand {
-    unsigned int limit:16;
-    unsigned int base:32;
-} __attribute__((packed));
-
-/* Magic strings */
-static const char version_string[]   = "COM32 Multiboot loader v0.2";
-static const char copyright_string[] = "Copyright (C) 2005-2006 Tim Deegan.";
-static const char module_separator[] = "---";
-
-
-/*
- *  Start of day magic, run from __start during library init.
- */
-
-static void __constructor check_version(void)
-    /* Check the SYSLINUX version.  Docs say we should be OK from v2.08,
-     * but in fact we crash on anything below v2.12 (when libc came in). */
-{
-    com32sys_t regs_in, regs_out;
-    const char *p, *too_old = "Fatal: SYSLINUX image is too old; "
-                              "mboot.c32 needs at least version 2.12.\r\n";
-
-    memset(&regs_in, 0, sizeof(regs_in));
-    regs_in.eax.l = 0x0001;  /* "Get version" */
-    __intcall(0x22, &regs_in, &regs_out);
-    if (regs_out.ecx.w[0] >= 0x020c) return;
-
-    /* Pointless: on older versions this print fails too. :( */
-    for (p = too_old ; *p ; p++) {
-        memset(&regs_in, 0, sizeof(regs_in));
-        regs_in.eax.b[1] = 0x02;      /* "Write character" */
-        regs_in.edx.b[0] = *p;
-        __intcall(0x21, &regs_in, &regs_out);
-    }
-
-    __intcall(0x20, &regs_in, &regs_out);  /* "Terminate program" */
-}
-
-
-static void __constructor grab_memory(void)
-    /* Runs before init_memory_arena() (com32/lib/malloc.c) to let
-     * the malloc() code know how much space it's allowed to use.
-     * We don't use malloc() directly, but some of the library code
-     * does (zlib, for example). */
-{
-    /* Find the stack pointer */
-    register char * sp;
-    asm volatile("movl %%esp, %0" : "=r" (sp));
-
-    /* Initialize the allocation of *run-time* memory: don't let ourselves
-     * overwrite the stack during the relocation later. */
-    max_run_addr = (size_t) sp - (MALLOC_SIZE + STACK_SIZE);
-
-    /* Move the end-of-memory marker: malloc() will use only memory
-     * above __mem_end and below the stack.  We will load files starting
-     * at the old __mem_end and working towards the new one, and allocate
-     * section descriptors at the top of that area, working down. */
-    next_load_addr = __mem_end;
-    section_addr = sp - (MALLOC_SIZE + STACK_SIZE);
-    section_count = 0;
-
-    /* But be careful not to move it the wrong direction if memory is
-     * tight.  Instead we'll fail more gracefully later, when we try to
-     * load a file and find that next_load_addr > section_addr. */
-    __mem_end = MAX(section_addr, next_load_addr);
-}
-
-
-
-
-/*
- *  Run-time memory map functions: allocating and recording allocations.
- */
-
-static int cmp_sections(const void *a, const void *b)
-    /* For sorting section descriptors by destination address */
-{
-    const section_t *sa = a;
-    const section_t *sb = b;
-    if (sa->dest < sb->dest) return -1;
-    if (sa->dest > sb->dest) return 1;
-    return 0;
-}
-
-
-static void add_section(size_t dest, char *src, size_t size)
-    /* Adds something to the list of sections to relocate. */
-{
-    section_t *sec;
-
-#ifdef DEBUG
-    printf("SECTION: %#8.8x --> %#8.8x (%#x)\n", (size_t) src, dest, size);
-#endif
-
-    section_addr -= sizeof (section_t);
-    if (section_addr < next_load_addr) {
-        printf("Fatal: out of memory allocating section descriptor.\n");
-        exit(1);
-    }
-    sec = (section_t *) section_addr;
-    section_count++;
-
-    sec->src = src;
-    sec->dest = dest;
-    sec->size = size;
-
-    /* Keep the list sorted */
-    qsort(sec, section_count, sizeof (section_t), cmp_sections);
-}
-
-
-static size_t place_low_section(size_t size, size_t align)
-    /* Find a space in the run-time memory map, below 640K */
-{
-    int i;
-    size_t start;
-    section_t *sections = (section_t *) section_addr;
-
-    start = MIN_RUN_ADDR;
-    start = (start + (align-1)) & ~(align-1);
-
-    /* Section list is sorted by destination, so can do this in one pass */
-    for (i = 0; i < section_count; i++) {
-        if (sections[i].dest < start + size) {
-            /* Hit the bottom of this section */
-            start = sections[i].dest + sections[i].size;
-            start = (start + (align-1)) & ~(align-1);
-        }
-    }
-    if (start + size < MEM_HOLE_START) return start;
-    else return 0;
-}
-
-
-static size_t place_module_section(size_t size, size_t align)
-    /* Find a space in the run-time memory map for this module. */
-{
-    /* Ideally we'd run through the sections looking for a free space
-     * like place_low_section() does, but some OSes (Xen, at least)
-     * assume that the bootloader has loaded all the modules
-     * consecutively, above the kernel.  So, what we actually do is
-     * keep a pointer to the highest address allocated so far, and
-     * always allocate modules there. */
-
-    size_t start = next_mod_run_addr;
-    start = (start + (align-1)) & ~(align-1);
-
-    if (start + size > max_run_addr) return 0;
-
-    next_mod_run_addr =&n