summaryrefslogtreecommitdiff
path: root/com32/sysdump
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-02-06 22:28:01 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-02-06 22:28:01 -0800
commit6f19ff5ce811655353712647e82f0dee22805108 (patch)
treebc01315a117d9a7c14ff8254c34af77b02acdfc9 /com32/sysdump
parent22c6d03bba83a3c68971e1927628ede12a3b618c (diff)
downloadsyslinux-6f19ff5ce811655353712647e82f0dee22805108.tar.gz
sysdump: add support for dumping DMI tables
Add support for dumping DMI tables; hopefully in a way that is compatible with dmidecode. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'com32/sysdump')
-rw-r--r--com32/sysdump/backend.h4
-rw-r--r--com32/sysdump/cpio.c12
-rw-r--r--com32/sysdump/dmi.c123
-rw-r--r--com32/sysdump/main.c84
-rw-r--r--com32/sysdump/memory.c3
-rw-r--r--com32/sysdump/sysdump.h1
6 files changed, 136 insertions, 91 deletions
diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h
index 343d2960..0be80c63 100644
--- a/com32/sysdump/backend.h
+++ b/com32/sysdump/backend.h
@@ -47,11 +47,15 @@ int init_data(struct backend *be, const char *argv[], size_t len);
int write_data(struct backend *be, const void *buf, size_t len, bool flush);
/* cpio.c */
+int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen,
+ const char *filename);
int cpio_init(struct backend *be, const char *argv[], size_t len);
int cpio_mkdir(struct backend *be, const char *filename);
int cpio_writefile(struct backend *be, const char *filename,
const void *data, size_t len);
int cpio_close(struct backend *be);
+#define MODE_FILE 0100644
+#define MODE_DIR 0040755
/* backends.c */
struct backend *get_backend(const char *name);
diff --git a/com32/sysdump/cpio.c b/com32/sysdump/cpio.c
index 120f7eb1..30e3d496 100644
--- a/com32/sysdump/cpio.c
+++ b/com32/sysdump/cpio.c
@@ -14,7 +14,7 @@
static uint32_t now;
-static int cpio_pad(struct backend *be)
+int cpio_pad(struct backend *be)
{
static char pad[4]; /* Up to 4 zero bytes */
if (be->dbytes & 3)
@@ -23,14 +23,16 @@ static int cpio_pad(struct backend *be)
return 0;
}
-static int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen,
- const char *filename)
+int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen,
+ const char *filename)
{
static uint32_t inode = 2;
char hdr[6+13*8+1];
int nlen = strlen(filename)+1;
int rv = 0;
+ cpio_pad(be);
+
sprintf(hdr, "%06o%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
070701, /* c_magic */
inode++, /* c_ino */
@@ -60,7 +62,7 @@ int cpio_init(struct backend *be, const char *argv[], size_t len)
int cpio_mkdir(struct backend *be, const char *filename)
{
- return cpio_hdr(be, 0040755, 0, filename);
+ return cpio_hdr(be, MODE_DIR, 0, filename);
}
int cpio_writefile(struct backend *be, const char *filename,
@@ -68,7 +70,7 @@ int cpio_writefile(struct backend *be, const char *filename,
{
int rv;
- rv = cpio_hdr(be, 0100644, len, filename);
+ rv = cpio_hdr(be, MODE_FILE, len, filename);
rv |= write_data(be, data, len, false);
rv |= cpio_pad(be);
diff --git a/com32/sysdump/dmi.c b/com32/sysdump/dmi.c
new file mode 100644
index 00000000..ad7c4523
--- /dev/null
+++ b/com32/sysdump/dmi.c
@@ -0,0 +1,123 @@
+/*
+ * Dump DMI information in a way hopefully compatible with dmidecode
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/cpu.h>
+#include "sysdump.h"
+#include "backend.h"
+
+struct dmi_header {
+ char signature[5];
+ uint8_t csum;
+ uint16_t tbllen;
+ uint32_t tbladdr;
+ uint16_t nstruc;
+ uint8_t revision;
+ uint8_t reserved;
+};
+
+struct smbios_header {
+ char signature[4];
+ uint8_t csum;
+ uint8_t len;
+ uint8_t major;
+ uint8_t minor;
+ uint16_t maxsize;
+ uint8_t revision;
+ uint8_t fmt[5];
+
+ struct dmi_header dmi;
+};
+
+static uint8_t checksum(const void *buf, size_t len)
+{
+ const uint8_t *p = buf;
+ uint8_t csum = 0;
+
+ while (len--)
+ csum += *p++;
+
+ return csum;
+}
+
+static bool is_old_dmi(size_t dptr)
+{
+ const struct dmi_header *dmi = (void *)dptr;
+
+ return !memcmp(dmi->signature, "_DMI_", 5) &&
+ !checksum(dmi, 0x0f);
+ return false;
+}
+
+static bool is_smbios(size_t dptr)
+{
+ const struct smbios_header *smb = (void *)dptr;
+
+ return !memcmp(smb->signature, "_SM_", 4) &&
+ !checksum(smb, smb->len) &&
+ is_old_dmi(dptr+16);
+}
+
+static void dump_smbios(struct backend *be, size_t dptr)
+{
+ const struct smbios_header *smb = (void *)dptr;
+ struct smbios_header smx = *smb;
+
+ cpio_hdr(be, MODE_FILE, smb->dmi.tbllen + 32, "dmidata");
+
+ /*
+ * Adjust the address of the smbios table to be 32, to
+ * make dmidecode happy. According to dmidecode, the checksum on
+ * the smbios structure doesn't need to be adjusted, for whatever
+ * reason...
+ */
+ smx.dmi.tbladdr = sizeof smx;
+ smx.dmi.csum -= checksum(&smb->dmi, 0x0f);
+
+ write_data(be, &smx, sizeof smx, false);
+ write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen, false);
+}
+
+static void dump_old_dmi(struct backend *be, size_t dptr)
+{
+ const struct dmi_header *dmi = (void *)dptr;
+ struct fake {
+ struct dmi_header dmi;
+ char pad[16];
+ } fake;
+
+ cpio_hdr(be, MODE_FILE, dmi->tbllen + 32, "dmidata");
+
+ /*
+ * Adjust the address of the smbios table to be 32, to
+ * make dmidecode happy. According to dmidecode, the checksum on
+ * the smbios structure doesn't need to be adjusted, for whatever
+ * reason...
+ */
+ fake.dmi = *dmi;
+ memset(&fake.pad, 0, sizeof fake.pad);
+ fake.dmi.tbladdr = sizeof fake;
+ fake.dmi.csum -= checksum(&fake.dmi, 0x0f);
+
+ write_data(be, &fake, sizeof fake, false);
+ write_data(be, (const void *)dmi->tbladdr, dmi->tbllen, false);
+}
+
+void dump_dmi(struct backend *be)
+{
+ size_t dptr;
+
+ /* Search for _SM_ or _DMI_ structure */
+ for (dptr = 0xf0000 ; dptr < 0x100000 ; dptr += 16) {
+ if (is_smbios(dptr)) {
+ dump_smbios(be, dptr);
+ break;
+ } else if (is_old_dmi(dptr)) {
+ dump_old_dmi(be, dptr);
+ break;
+ }
+ }
+}
diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c
index decb86d0..ffe3430c 100644
--- a/com32/sysdump/main.c
+++ b/com32/sysdump/main.c
@@ -30,95 +30,13 @@ __noreturn die(const char *msg)
exit(1);
}
-#if 0
-static void get_bytes(void *buf, size_t len, struct file_info *finfo,
- size_t pos)
-{
- pos += (size_t) finfo->pvt; /* Add base */
- memcpy(buf, (void *)pos, len);
-}
-
-int main(int argc, char *argv[])
-{
- uint16_t bios_ports[4];
- const char *prefix;
- char filename[1024];
- int i;
- static struct serial_if sif = {
- .read = serial_read,
- .write = serial_write,
- };
- struct file_info finfo;
- const char ymodem_banner[] = "Now begin Ymodem download...\r\n";
- bool srec = false;
-
- if (argv[1][0] == '-') {
- srec = argv[1][1] == 's';
- argc--;
- argv++;
- }
-
- if (argc < 4)
- die("usage: memdump [-s] port prefix start,len...");
-
- finfo.pvt = (void *)0x400;
- get_bytes(bios_ports, 8, &finfo, 0); /* Get BIOS serial ports */
-
- for (i = 0; i < 4; i++)
- printf("ttyS%i (COM%i) is at %#x\n", i, i + 1, bios_ports[i]);
-
- sif.port = strtoul(argv[1], NULL, 0);
- if (sif.port <= 3) {
- sif.port = bios_ports[sif.port];
- }
-
- if (serial_init(&sif))
- die("failed to initialize serial port");
-
- prefix = argv[2];
-
- if (!srec) {
- puts("Printing prefix...");
- sif.write(&sif, ymodem_banner, sizeof ymodem_banner - 1);
- }
-
- for (i = 3; i < argc; i++) {
- uint32_t start, len;
- char *ep;
-
- start = strtoul(argv[i], &ep, 0);
- if (*ep != ',')
- die("invalid range specification");
- len = strtoul(ep + 1, NULL, 0);
-
- sprintf(filename, "%s%#x-%#x.bin", prefix, start, len);
- finfo.name = filename;
- finfo.size = len;
- finfo.pvt = (void *)start;
-
- printf("Sending %s...\n", filename);
-
- if (srec)
- send_srec(&sif, &finfo, get_bytes);
- else
- send_ymodem(&sif, &finfo, get_bytes);
- }
-
- if (!srec) {
- puts("Sending closing signature...");
- end_ymodem(&sif);
- }
-
- return 0;
-}
-#endif
-
static void dump_all(struct backend *be, const char *argv[], size_t len)
{
cpio_init(be, argv, len);
dump_memory(be);
+ dump_dmi(be);
dump_vesa_tables(be);
cpio_close(be);
diff --git a/com32/sysdump/memory.c b/com32/sysdump/memory.c
index 9d391ecd..e7108d1e 100644
--- a/com32/sysdump/memory.c
+++ b/com32/sysdump/memory.c
@@ -44,7 +44,4 @@ void dump_memory(struct backend *be)
if (lowmem)
dump_memory_range(be, lowmem, zero_addr, lowmem_len);
-
- /* Look for a DMI header */
}
-
diff --git a/com32/sysdump/sysdump.h b/com32/sysdump/sysdump.h
index 87f7e2b6..df9da311 100644
--- a/com32/sysdump/sysdump.h
+++ b/com32/sysdump/sysdump.h
@@ -4,6 +4,7 @@
struct backend;
void dump_memory(struct backend *);
+void dump_dmi(struct backend *);
void dump_vesa_tables(struct backend *);
#endif /* SYSDUMP_H */