int main(int argc, char * argv[]) { mach_port_t masterPort; io_service_t service = MACH_PORT_NULL; CFDataRef dataRef; UInt16 maxStructureSize, structureCount = 0; UInt16 tableLength = 0, droppedTables = 0; UInt16 newTableLength = 0; // UInt32 * shadowTableData = NULL; IOMasterPort(MACH_PORT_NULL, &masterPort); service = IOServiceGetMatchingService(masterPort, IOServiceMatching("AppleSMBIOS")); if (service) { #if DEBUG printf("\nHave AppleSMBIOS\n"); #endif dataRef = (CFDataRef) IORegistryEntryCreateCFProperty(service, CFSTR("SMBIOS-EPS"), kCFAllocatorDefault, kNilOptions); if (dataRef) { // We could use isA_CFData(dataRef) {} here, but that would force us to include // another file, which in my opinion would be overkill (dataRef should always be there). #if DEBUG printf("Have SMBIOS-EPS dataRef\n\n"); #endif struct SMBEntryPoint * eps = (struct SMBEntryPoint *) CFDataGetBytePtr(dataRef); tableLength = eps->dmi.tableLength; /* shadowTableData = malloc(tableLength); bzero(shadowTableData, tableLength); bcopy((void *)(unsigned int)eps->dmi.tableAddress, shadowTableData, tableLength); */ #if DEBUG // _SM_ eps->anchor[4] = 0; // Prevent garbage output. printf("eps.anchor : %s\n", eps->anchor); printf("eps.checksum : 0x02%x\n", eps->checksum); printf("eps.entryPointLength : 0x%x\n", eps->entryPointLength); printf("eps.majorVersion : 0x%02x\n", eps->majorVersion); printf("eps.minorVersion : 0x%02x\n", eps->minorVersion); #endif maxStructureSize = eps->maxStructureSize; #if DEBUG printf("eps.maxStructureSize : 0x%04x\n", maxStructureSize); printf("eps.entryPointRevision: 0x%02x\n", eps->entryPointRevision); printf("eps.formattedArea : %s\n\n", eps->formattedArea); // _DMI_ eps->dmi.anchor[5] = 0; // Prevent garbage output. printf("eps.dmi.anchor : %s\n", eps->dmi.anchor); printf("eps.dmi.checksum : 0x%02x\n", eps->dmi.checksum); printf("eps.dmi.tableLength : 0x%04x\n", tableLength); // eps->dmi.tableLength); printf("eps.dmi.tableAddress : 0x%08x\n", (unsigned int)eps->dmi.tableAddress); #endif structureCount = eps->dmi.structureCount; #if DEBUG printf("eps.dmi.structureCount: 0x%04x\n", structureCount); printf("eps.dmi.bcdRevision : 0x%x\n", eps->dmi.bcdRevision); #endif // Done with dataRef / release it. CFRelease(dataRef); } #if DEBUG printf("\n"); #endif dataRef = (CFDataRef) IORegistryEntryCreateCFProperty(service, CFSTR("SMBIOS"), kCFAllocatorDefault, kNilOptions); if (dataRef) { // We could use isA_CFData(dataRef) {} here, but that would force us to include another // header file, which in my opinion would be overkill as dataRef should always be there. #if DEBUG printf("Have SMBIOS dataRef\n"); #endif UInt32 * tableData = (UInt32 *) CFDataGetBytePtr(dataRef); #if VERBOSE UInt16 numBytes = (int) CFDataGetLength(dataRef); printf("\nNumber of bytes: %d (Original SMBIOS table)\n", numBytes); #endif SMBStructHeader * header; const UInt8 * tablePtr = (const UInt8 *) tableData; const UInt8 * tableEndPtr = tablePtr + tableLength; const UInt8 * tableStructureStart = 0; const UInt8 * droppedTableStructureStart = 0; const UInt8 * tableBuffer = malloc(tableLength); // int index = 0; int maxStructureSize = 0; int newStructureCount = 0; int structureLength = 0; SMBWord newHandle = 0; bzero((void *)tableBuffer, sizeof(tableBuffer)); while (structureCount-- && (tableEndPtr > tablePtr + sizeof(SMBStructHeader))) { droppedTableStructureStart = tableStructureStart = 0; header = (SMBStructHeader *) tablePtr; if (header->length > tableEndPtr - tablePtr) { break; } switch (header->type) { case kSMBTypeBIOSInformation: // Type 0 case kSMBTypeSystemInformation: // Type 1 case kSMBTypeBaseBoard: // Type 2 case kSMBTypeProcessorInformation: // Type 4 // case kSMBTypeMemoryModule: // Type 6 // case kSMBTypeSystemSlot: // Type 9 case kSMBTypePhysicalMemoryArray: // Type 16 case kSMBTypeMemoryDevice: // Type 17 case kSMBTypeEndOfTable: // Type 127 case kSMBTypeFirmwareVolume: // Type 128 case kSMBTypeMemorySPD: // Type 130 case kSMBTypeOemProcessorType: // Type 131 case kSMBTypeOemProcessorBusSpeed: // Type 132 newStructureCount++; tableStructureStart = tablePtr; header->handle = newHandle++; // printf("type: %d, handle: %d\n", header->type, header->handle); break; default: droppedTables++; droppedTableStructureStart = tablePtr; } VERBOSE_DUMP("Table: %3d %37s @%p Formatted area: %2d bytes ", header->type, tableDescriptions[header->type], tablePtr, header->length); // Skip the formatted area of the structure. tablePtr += header->length; // Skip the unformatted structure area at the end (strings). for (; tableEndPtr > tablePtr + sizeof(SMBStructHeader); tablePtr++) { // Look for a terminating double NULL. if (tablePtr[0] == 0 && tablePtr[1] == 0) { tablePtr += 2; break; } } if (tableStructureStart) { structureLength = tablePtr - tableStructureStart; VERBOSE_DUMP("Structure length: %3d bytes.\n", structureLength); bcopy((void *)tableStructureStart, (void *)tableBuffer + newTableLength, structureLength); newTableLength += structureLength; // Taking care of eps->maxStructureSize if (maxStructureSize < structureLength) { maxStructureSize = structureLength; } } else if (droppedTableStructureStart) { structureLength = tablePtr - droppedTableStructureStart; VERBOSE_DUMP("Structure length: %3d bytes (dropped).\n", structureLength); } } VERBOSE_DUMP("\nDropped tables: %2d.\n", droppedTables); dumpStaticTableData(tableBuffer, maxStructureSize, newStructureCount, newTableLength); free((void *)tableBuffer); // Done with dataRef / release it. CFRelease(dataRef); } // Done with the service / release it. IOObjectRelease(service); } exit(0); }
int main(int argc, char * argv[]) { char dirspec[128]; int filedesc = 0; struct stat my_sb; if (argc == 2) { uid_t real_uid = getuid(); uid_t euid = geteuid(); #if DEBUG printf("UID: %u EUID: %u\n", real_uid, euid); #endif // Under sudo, getuid and geteuid return 0. if (real_uid != 0 || euid != 0) { printf("Error: Not root. Use sudo ./smbios2struct4 [filename without extension]\n"); exit (-1); } } mach_port_t masterPort; io_service_t service = MACH_PORT_NULL; CFDataRef dataRef; UInt16 maxStructureSize, structureCount = 0; UInt16 tableLength = 0, droppedTables = 0; UInt16 newTableLength = 0; IOMasterPort(MACH_PORT_NULL, &masterPort); //================================================================================== io_registry_entry_t efi = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/efi"); if (efi == IO_OBJECT_NULL) { #if DEBUG printf("FAILURE: Unable to locate EFI registry entry.\n"); #endif exit(-1); } else { #if DEBUG printf("OK\n"); #endif dataRef = (CFDataRef) IORegistryEntryCreateCFProperty(efi, CFSTR("device-properties"), kCFAllocatorDefault, kNilOptions); if (dataRef) { UInt32 * deviceProperties = (UInt32 *) CFDataGetBytePtr(dataRef); UInt16 devicePropertiesBytes = (int) CFDataGetLength(dataRef); #if DEBUG printf("Property 'device-properties' %d bytes found.", numBytes); #endif if ((argc == 2) && (devicePropertiesBytes)) // Write to file? { // Sanity check for required directory. if (stat("/Extra", &my_sb) != 0) { mkdir("/Extra", (S_IRWXU | S_IRWXG | S_IRWXO)); } // Sanity check for required directory. if (stat("/Extra/EFI", &my_sb) != 0) { mkdir("/Extra/EFI", (S_IRWXU | S_IRWXG | S_IRWXO)); } sprintf (dirspec, "/Extra/EFI/%s.bin", argv[1]); filedesc = open(dirspec, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (filedesc == -1) { printf("Error: Unable to open file!\n"); } else { int status = write(filedesc, deviceProperties, devicePropertiesBytes); if (status != devicePropertiesBytes) { printf("status %d, saved %d bytes\n", status, devicePropertiesBytes); } else { printf("%d bytes written to: %s\n", devicePropertiesBytes, dirspec); } } close (filedesc); } } #if DEBUG else { printf("FAILURE: Unable to locate ':/efi/device-properties'\n"); } #endif } //================================================================================== service = IOServiceGetMatchingService(masterPort, IOServiceMatching("AppleSMBIOS")); if (service) { #if DEBUG printf("\nAppleSMBIOS found\n"); #endif dataRef = (CFDataRef) IORegistryEntryCreateCFProperty(service, CFSTR("SMBIOS-EPS"), kCFAllocatorDefault, kNilOptions); if (dataRef) { // We could use isA_CFData(dataRef) {} here, but that would force us to include // another file, which in my opinion would be overkill (dataRef should always be there). #if DEBUG printf("Have SMBIOS-EPS dataRef\n\n"); #endif struct SMBEntryPoint * eps = (struct SMBEntryPoint *) CFDataGetBytePtr(dataRef); tableLength = eps->dmi.tableLength; /* shadowTableData = malloc(tableLength); bzero(shadowTableData, tableLength); bcopy((void *)(unsigned int)eps->dmi.tableAddress, shadowTableData, tableLength); */ #if DEBUG // _SM_ eps->anchor[4] = 0; // Prevent garbage output. printf("eps.anchor : %s\n", eps->anchor); printf("eps.checksum : 0x02%x\n", eps->checksum); printf("eps.entryPointLength : 0x%x\n", eps->entryPointLength); printf("eps.majorVersion : 0x%02x\n", eps->majorVersion); printf("eps.minorVersion : 0x%02x\n", eps->minorVersion); #endif maxStructureSize = eps->maxStructureSize; #if DEBUG printf("eps.maxStructureSize : 0x%04x\n", maxStructureSize); printf("eps.entryPointRevision: 0x%02x\n", eps->entryPointRevision); printf("eps.formattedArea : %s\n\n", eps->formattedArea); // _DMI_ eps->dmi.anchor[5] = 0; // Prevent garbage output. printf("eps.dmi.anchor : %s\n", eps->dmi.anchor); printf("eps.dmi.checksum : 0x%02x\n", eps->dmi.checksum); printf("eps.dmi.tableLength : 0x%04x\n", tableLength); // eps->dmi.tableLength); printf("eps.dmi.tableAddress : 0x%08x\n", (unsigned int)eps->dmi.tableAddress); #endif structureCount = eps->dmi.structureCount; #if DEBUG printf("eps.dmi.structureCount: 0x%04x\n", structureCount); printf("eps.dmi.bcdRevision : 0x%x\n", eps->dmi.bcdRevision); #endif // Done with dataRef / release it. CFRelease(dataRef); } #if DEBUG printf("\n"); #endif dataRef = (CFDataRef) IORegistryEntryCreateCFProperty(service, CFSTR("SMBIOS"), kCFAllocatorDefault, kNilOptions); if (dataRef) { // We could use isA_CFData(dataRef) {} here, but that would force us to include another // header file, which in my opinion would be overkill as dataRef should always be there. #if DEBUG printf("Have SMBIOS dataRef\n"); #endif UInt32 * tableData = (UInt32 *) CFDataGetBytePtr(dataRef); #if VERBOSE UInt16 numBytes = (int) CFDataGetLength(dataRef); printf("\nNumber of bytes: %d (Original SMBIOS table)\n", numBytes); #endif SMBStructHeader * header; const UInt8 * tablePtr = (const UInt8 *) tableData; const UInt8 * tableEndPtr = tablePtr + tableLength; const UInt8 * tableStructureStart = 0; const UInt8 * droppedTableStructureStart = 0; const UInt8 * tableBuffer = malloc(tableLength); // int index = 0; int maxStructureSize = 0; int newStructureCount = 0; int structureLength = 0; SMBWord newHandle = 0; bzero((void *)tableBuffer, sizeof(tableBuffer)); while (structureCount-- && (tableEndPtr > tablePtr + sizeof(SMBStructHeader))) { droppedTableStructureStart = tableStructureStart = 0; header = (SMBStructHeader *) tablePtr; if (header->length > tableEndPtr - tablePtr) { break; } switch (header->type) { case kSMBTypeBIOSInformation: // Type 0 case kSMBTypeSystemInformation: // Type 1 case kSMBTypeBaseBoard: // Type 2 case kSMBTypeProcessorInformation: // Type 4 // case kSMBTypeMemoryModule: // Type 6 // case kSMBTypeSystemSlot: // Type 9 case kSMBTypePhysicalMemoryArray: // Type 16 case kSMBTypeMemoryDevice: // Type 17 case kSMBTypeEndOfTable: // Type 127 case kSMBTypeFirmwareVolume: // Type 128 case kSMBTypeMemorySPD: // Type 130 case kSMBTypeOemProcessorType: // Type 131 case kSMBTypeOemProcessorBusSpeed: // Type 132 newStructureCount++; tableStructureStart = tablePtr; header->handle = newHandle++; // printf("type: %d, handle: %d\n", header->type, header->handle); break; default: droppedTables++; droppedTableStructureStart = tablePtr; } VERBOSE_DUMP("Table: %3d %37s @%p Formatted area: %2d bytes ", header->type, tableDescriptions[header->type], tablePtr, header->length); // Skip the formatted area of the structure. tablePtr += header->length; // Skip the unformatted structure area at the end (strings). for (; tableEndPtr > tablePtr + sizeof(SMBStructHeader); tablePtr++) { // Look for a terminating double NULL. if (tablePtr[0] == 0 && tablePtr[1] == 0) { tablePtr += 2; break; } } if (tableStructureStart) { structureLength = tablePtr - tableStructureStart; VERBOSE_DUMP("Structure length: %3d bytes.\n", structureLength); bcopy((void *)tableStructureStart, (void *)tableBuffer + newTableLength, structureLength); newTableLength += structureLength; // Taking care of eps->maxStructureSize if (maxStructureSize < structureLength) { maxStructureSize = structureLength; } } else if (droppedTableStructureStart) { structureLength = tablePtr - droppedTableStructureStart; VERBOSE_DUMP("Structure length: %3d bytes (dropped).\n", structureLength); } } VERBOSE_DUMP("\nDropped tables: %2d.\n", droppedTables); if (argc == 2) // Write to file? { // Sanity check for required directory. if (stat("/Extra/SMBIOS", &my_sb) != 0) { mkdir("/Extra/SMBIOS", (S_IRWXU | S_IRWXG | S_IRWXO)); } sprintf (dirspec, "/Extra/SMBIOS/%s.bin", argv[1]); filedesc = open(dirspec, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (filedesc == -1) { printf("Error: Unable to open file!\n"); } else { newTableLength = round2((newTableLength + 2), 4); VERBOSE_DUMP("newTableLength: %d\n", newTableLength); int status = write(filedesc, tableBuffer, newTableLength); if (status != newTableLength) { printf("status %d, saved %d bytes\n", status, newTableLength); } else { printf("%d bytes written to: %s\n", newTableLength, dirspec); } } close (filedesc); } else { dumpStaticTableData(tableBuffer, maxStructureSize, newStructureCount, newTableLength); } free((void *)tableBuffer); // Done with dataRef / release it. CFRelease(dataRef); } // Done with the service / release it. IOObjectRelease(service); } exit(0); }