summaryrefslogtreecommitdiff
path: root/dmidecode.c
diff options
context:
space:
mode:
authorJean Delvare <jdelvare@suse.de>2006-05-10 11:28:04 +0000
committerJean Delvare <jdelvare@suse.de>2006-05-10 11:28:04 +0000
commitdbe991a719c9ac0a4f390f30221cec2d2dfc45fc (patch)
tree1a3598d42f6af99114c7cafc6e411d39dc638400 /dmidecode.c
parenta51392dacd66a5d1dd44abbf803ce60eae310883 (diff)
downloaddmidecode-git-dbe991a719c9ac0a4f390f30221cec2d2dfc45fc.tar.gz
Detect EFI at run-time rather than compilation-time. Based on an original
patch from Matthew Garrett. This will make x86 binaries work for both PC systems with BIOS and Macintosh systems with EFI. Also prevent a possible, though unlikely, NULL-pointer dereference in the EFI code.
Diffstat (limited to 'dmidecode.c')
-rw-r--r--dmidecode.c106
1 files changed, 61 insertions, 45 deletions
diff --git a/dmidecode.c b/dmidecode.c
index 3763b04..d967c62 100644
--- a/dmidecode.c
+++ b/dmidecode.c
@@ -52,10 +52,6 @@
#include <stdlib.h>
#include <unistd.h>
-#ifdef __ia64__
-#define USE_EFI
-#endif /* __ia64__ */
-
#include "version.h"
#include "config.h"
#include "types.h"
@@ -3913,7 +3909,6 @@ static int smbios_decode(u8 *buf, const char *devmem)
return 0;
}
-#ifndef USE_EFI
static int legacy_decode(u8 *buf, const char *devmem)
{
if(checksum(buf, 0x0F))
@@ -3928,18 +3923,60 @@ static int legacy_decode(u8 *buf, const char *devmem)
return 0;
}
-#endif /* USE_EFI */
+
+/*
+ * Probe for EFI interface
+ */
+#define EFI_NOT_FOUND (-1)
+#define EFI_NO_SMBIOS (-2)
+static int address_from_efi(size_t *address)
+{
+ FILE *efi_systab;
+ const char *filename;
+ char linebuf[64];
+ int ret;
+
+ *address=0; /* Prevent compiler warning */
+
+ /*
+ * Linux up to 2.6.6: /proc/efi/systab
+ * Linux 2.6.7 and up: /sys/firmware/efi/systab
+ */
+ if((efi_systab=fopen(filename="/sys/firmware/efi/systab", "r"))==NULL
+ && (efi_systab=fopen(filename="/proc/efi/systab", "r"))==NULL)
+ {
+ /* No EFI interface, fallback to memory scan */
+ return EFI_NOT_FOUND;
+ }
+ ret=EFI_NO_SMBIOS;
+ while((fgets(linebuf, sizeof(linebuf)-1, efi_systab))!=NULL)
+ {
+ char *addrp=strchr(linebuf, '=');
+ *(addrp++)='\0';
+ if(strcmp(linebuf, "SMBIOS")==0)
+ {
+ *address=strtoul(addrp, NULL, 0);
+ if(!(opt.flags & FLAG_QUIET))
+ printf("# SMBIOS entry point at 0x%08lx\n",
+ (unsigned long)*address);
+ ret=0;
+ break;
+ }
+ }
+ if(fclose(efi_systab)!=0)
+ perror(filename);
+
+ if(ret==EFI_NO_SMBIOS)
+ fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
+ return ret;
+}
int main(int argc, char * const argv[])
{
int ret=0; /* Returned value */
int found=0;
size_t fp;
-#ifdef USE_EFI
- FILE *efi_systab;
- const char *filename;
- char linebuf[64];
-#endif /* USE_EFI */
+ int efi;
u8 *buf;
if(sizeof(u8)!=1 || sizeof(u16)!=2 || sizeof(u32)!=4 || '\0'!=0)
@@ -3973,37 +4010,15 @@ int main(int argc, char * const argv[])
if(!(opt.flags & FLAG_QUIET))
printf("# dmidecode %s\n", VERSION);
-#ifdef USE_EFI
- /*
- * Linux up to 2.6.6-rc2: /proc/efi/systab
- * Linux 2.6.6-rc3 and up: /sys/firmware/efi/systab
- */
- if((efi_systab=fopen(filename="/proc/efi/systab", "r"))==NULL
- && (efi_systab=fopen(filename="/sys/firmware/efi/systab", "r"))==NULL)
- {
- perror(filename);
- ret=1;
- goto exit_free;
- }
- fp=0;
- while((fgets(linebuf, sizeof(linebuf)-1, efi_systab))!=NULL)
- {
- char* addr=memchr(linebuf, '=', strlen(linebuf));
- *(addr++)='\0';
- if(strcmp(linebuf, "SMBIOS")==0)
- {
- fp=strtoul(addr, NULL, 0);
- if(!(opt.flags & FLAG_QUIET))
- printf("# SMBIOS entry point at 0x%08lx\n", fp);
- }
- }
- if(fclose(efi_systab)!=0)
- perror(filename);
- if(fp==0)
+ /* First try EFI (ia64, Intel-based Mac) */
+ efi=address_from_efi(&fp);
+ switch(efi)
{
- fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
- ret=1;
- goto exit_free;
+ case EFI_NOT_FOUND:
+ goto memory_scan;
+ case EFI_NO_SMBIOS:
+ ret=1;
+ goto exit_free;
}
if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL)
@@ -4014,9 +4029,10 @@ int main(int argc, char * const argv[])
if(smbios_decode(buf, opt.devmem))
found++;
-
- free(buf);
-#else /* USE_EFI */
+ goto done;
+
+memory_scan:
+ /* Fallback to memory scan (x86, x86_64) */
if((buf=mem_chunk(0xF0000, 0x10000, opt.devmem))==NULL)
{
ret=1;
@@ -4038,8 +4054,8 @@ int main(int argc, char * const argv[])
}
}
+done:
free(buf);
-#endif /* USE_EFI */
if(!found && !(opt.flags & FLAG_QUIET))
printf("# No SMBIOS nor DMI entry point found, sorry.\n");