Chameleon Applications

Chameleon Applications Svn Source Tree

Root/trunk/ChameleonPrefPane/Sources/SmbiosExtractor.mm

  • Property svn:executable set to *
1//
2// SmbiosExtractor.mm
3// ChameleonPrefPane
4//
5// Created by Rekursor on 11-11-27.
6//
7
8#import "SmbiosExtractor.h"
9#include "ShellProcess.h"
10#include "string_util.h"
11#include "smbios.h"
12#include "PropertyList.h"
13#include "smbios.h"
14#include <stdio.h>
15#ifndef DEBUG_SMBIOS
16#define DEBUG_SMBIOS 0
17#endif
18#if 0
19#define DBG(x...)printf(x)
20#else
21#define DBG(x...)
22#endif
23static SMBWord minorVersion;
24
25static char* getSMBStringForField(SMBStructHeader *structHeader, uint8_t field)
26{
27uint8_t *stringPtr = ((uint8_t *)structHeader) + structHeader->length;
28static char empty[2] = "";
29if (!field)
30return empty;
31
32 for (field--; field != 0 && strlen((char *)stringPtr) > 0;
33 field--, stringPtr = (uint8_t *)((unsigned long )stringPtr + strlen((char *)stringPtr) + 1));
34
35return ( char*) (stringPtr ? (char*) stringPtr : empty);
36}
37
38#define SHVAL(field) [NSString stringWithUTF8String: getSMBStringForField((SMBStructHeader *)structHeader, structHeader->field)]
39#define SHVAL2(f,g) SHVAL(f),SHVAL(g)
40#define SHVAL3(f,g,h) SHVAL2(f,g),SHVAL(h)
41#define SHVAL4(f,g,h,i) SHVAL2(f,g),SHVAL2(h,i)
42#define SHVAL5(f,g,h,i,j) SHVAL4(f,g,h,i),SHVAL(j)
43#define SHVAL6(f,g,h,i,j,k) SHVAL5(f,g,h,i,j),SHVAL(k)
44#define SHVAL7(f,g,h,i,j,k,l) SHVAL6(f,g,h,i,j,k),SHVAL(l)
45
46#define MHZ(f) [NSString stringWithFormat:@"%d MHZ", (int)structHeader->f]
47#define DEC(f) [NSString stringWithFormat:@"%d", (int)structHeader->f]
48#define LLX(f) [NSString stringWithFormat:@"%llX", structHeader->f]
49#define HEX32(f) [NSString stringWithFormat:@"0x%08X", (int)structHeader->f]
50#define HEX16(f) [NSString stringWithFormat:@"0x%04X", (int)structHeader->f]
51#define HEX8(f) [NSString stringWithFormat:@"%0x02X", (int)structHeader->f]
52
53@implementation SmbiosExtractor
54
55@synthesize dict;
56@synthesize smString;
57@synthesize bufSize;
58-(id) init
59{
60self = [super init];
61if (self!=nil)
62{
63[ self extractSmBios];
64}
65
66return self;
67}
68
69-(void) cleanup
70{
71if (buffer!=nil)
72{
73delete [] buffer;
74buffer = nil;
75bufSize=0;
76smString = nil;
77}
78
79if (smString!=nil)
80{
81[smString release];
82smString = nil;
83}
84
85if (dict!=nil)
86{
87[dict release];
88dict = nil;
89}
90}
91
92-(void) dealloc
93{
94[self cleanup ];
95[super dealloc];
96}
97
98-(NSString*) description
99{
100return [dict description];
101}
102
103-(NSUInteger) extractSmBios
104{
105
106const char* SmbiosCmd = "ioreg -lw0 | grep \"\\\"SMBIOS\\\" = <\"";
107const char* SmbiosTag = "\"SMBIOS\" = <";
108ShellProcess p(SmbiosCmd);
109char line[8192]="";
110const size_t tagLen= strlen(SmbiosTag);
111
112if (p.get_line(line, sizeof(line)) )
113{
114const char * p = strstr(line, SmbiosTag)+ tagLen;
115std::string s = trim(p, " \t\r\n>");
116NSLog(@"Found SMBIOS (%d) [%s]", s.length(), s.c_str() );
117
118[self cleanup];
119
120self.dict = [NSMutableDictionary dictionaryWithCapacity:32];
121
122self.smString = [NSString stringWithUTF8String:s.c_str()];
123bufSize = s.length()/2;
124buffer = new UInt8[bufSize];
125
126for(size_t pos =0; pos < bufSize; pos++)
127{
128buffer[pos] = (HexToDec(s[pos*2])*16 + HexToDec(s[pos*2+1]));
129}
130
131[self decodeSMBIOSTableFrom:buffer to: buffer+bufSize];
132}
133
134return 0;
135}
136
137-(NSString*) stringFrom:(NSUInteger) start withLen:(NSUInteger) len
138{
139return [smString substringWithRange: NSMakeRange(start*2, len) ];
140}
141
142-(UInt8) ByteFrom:(NSUInteger) position
143{
144return position < bufSize ? buffer[position]: 0;
145}
146
147-(BOOL) save:(NSString*) path
148{
149NSString * error;
150id plist = [NSPropertyListSerialization dataFromPropertyList:(id)dict
151 format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
152
153[plist writeToFile:path atomically:YES];
154
155return YES;
156}
157#define ADD_HANDLE(text) [dict setValue:innerDict forKey: [NSString stringWithFormat:@"%@ (0x%02x)", text, (int) structHeader->header.handle] ]
158//-------------------------------------------------------------------------------------------------------------------------
159// BIOSInformation
160//-------------------------------------------------------------------------------------------------------------------------
161-(void) decodeBIOSInformation:(SMBBIOSInformation *)structHeader
162{
163NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
164[NSArray arrayWithObjects: SHVAL3(vendor, version, releaseDate), nil ]
165 forKeys: [NSArray arrayWithObjects:@"Vendor", @"Version", @"Release Date", nil]];
166
167ADD_HANDLE(@"BIOS Information");
168
169DBG("BIOSInformation:\n");
170DBG("\tvendor: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->vendor));
171DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
172DBG("\treleaseDate: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->releaseDate));
173DBG("\n");
174}
175
176//-------------------------------------------------------------------------------------------------------------------------
177// SystemInformation
178//-------------------------------------------------------------------------------------------------------------------------
179-(void) decodeSystemInformation:(SMBSystemInformation *)structHeader
180{
181NSDictionary* innerDict =
182[NSDictionary dictionaryWithObjects:
183[NSArray arrayWithObjects: SHVAL4(manufacturer, productName, version, serialNumber), nil ]
184forKeys: [NSArray arrayWithObjects:@"Manufacturer", @"Product Name", @"Version", @"Serial Number", nil]];
185
186ADD_HANDLE(@"System Information");
187
188DBG("SystemInformation:\n");
189DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
190DBG("\tproductName: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->productName));
191DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
192DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
193
194if (minorVersion < 1 || structHeader->header.length < 25)
195{
196DBG("\n");
197return;
198}
199uint8_t *uuid = structHeader->uuid;
200DBG("\tuuid: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02x%02X-%02X%02X%02X%02X%02X%02X\n",
201uuid[0], uuid[1], uuid[2], uuid[3],
202uuid[4], uuid[5],
203uuid[6], uuid[7],
204uuid[8], uuid[9],
205uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
206DBG("\twakeupReason: 0x%x\n", structHeader->wakeupReason);
207
208if (minorVersion < 4 || structHeader->header.length < 27)
209{
210DBG("\n");
211return;
212}
213DBG("\tskuNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->skuNumber));
214DBG("\tfamily: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->family));
215DBG("\n");
216}
217
218//-------------------------------------------------------------------------------------------------------------------------
219// BaseBoard
220//-------------------------------------------------------------------------------------------------------------------------
221-(void) decodeBaseBoard:(SMBBaseBoard *) structHeader
222{
223NSDictionary* innerDict =
224[NSDictionary dictionaryWithObjects:
225 [NSArray arrayWithObjects: SHVAL7(manufacturer, product, version, serialNumber, assetTagNumber, locationInChassis, boardType), nil ]
226forKeys: [NSArray arrayWithObjects:@"Manufacturer", @"Product", @"Version", @"Serial Number",
227 @"Asset Tag Number", @"Location In Chassis", @"Board Type", nil]];
228
229ADD_HANDLE(@"Base Board");
230
231DBG("BaseBoard:\n");
232DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
233DBG("\tproduct: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->product));
234DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
235DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
236DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));
237DBG("\tlocationInChassis: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->locationInChassis));
238DBG("\tboardType: 0x%X\n", structHeader->boardType);
239DBG("\n");
240}
241
242//-------------------------------------------------------------------------------------------------------------------------
243// SystemEnclosure
244//-------------------------------------------------------------------------------------------------------------------------
245-(void) decodeSystemEnclosure:(SMBSystemEnclosure *) structHeader
246{
247NSDictionary* innerDict =
248[NSDictionary dictionaryWithObjects:
249 [NSArray arrayWithObjects: SHVAL5(manufacturer, type, version, serialNumber, assetTagNumber), nil ]
250forKeys: [NSArray arrayWithObjects:@"Manufacturer", @"Type", @"Version", @"Serial Number", @"Asset Tag Number", nil]];
251
252ADD_HANDLE(@"System Enclosure");
253
254DBG("SystemEnclosure:\n");
255DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
256DBG("\ttype: %d\n", structHeader->type);
257DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
258DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
259DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));
260DBG("\n");
261}
262
263//-------------------------------------------------------------------------------------------------------------------------
264// ProcessorInformation
265//-------------------------------------------------------------------------------------------------------------------------
266-(void) decodeProcessorInformation:(SMBProcessorInformation *) structHeader
267{
268NSDictionary* clockDict = [NSDictionary dictionaryWithObjects:
269 [NSArray arrayWithObjects: MHZ(externalClock), MHZ(maximumClock), MHZ(currentClock), nil ]
270forKeys: [NSArray arrayWithObjects:@"External", @"Maximum", @"Current", nil]];
271
272NSDictionary* procDict = [NSDictionary dictionaryWithObjects:
273 [NSArray arrayWithObjects: SHVAL(socketDesignation), DEC(processorType), HEX16(processorFamily), SHVAL(manufacturer),
274 LLX(processorID), SHVAL(processorVersion), nil ]
275forKeys: [NSArray arrayWithObjects:@"Socket", @"Type", @"Family", @"Manufacturer", @"ID", @"Version", nil]];
276
277NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
278 [NSArray arrayWithObjects: procDict, clockDict, nil ]
279forKeys: [NSArray arrayWithObjects:@"Processor", @"Clock", nil]];
280
281ADD_HANDLE(@"Processor Information");
282
283DBG("ProcessorInformation:\n");
284DBG("\tsocketDesignation: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->socketDesignation));
285DBG("\tprocessorType: %d\n", structHeader->processorType);
286DBG("\tprocessorFamily: 0x%X\n", structHeader->processorFamily);
287DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
288DBG("\tprocessorID: 0x%llX\n", structHeader->processorID);
289DBG("\tprocessorVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->processorVersion));
290DBG("\texternalClock: %dMHz\n", structHeader->externalClock);
291DBG("\tmaximumClock: %dMHz\n", structHeader->maximumClock);
292DBG("\tcurrentClock: %dMHz\n", structHeader->currentClock);
293
294if (minorVersion >= 3 && structHeader->header.length >= 35)
295{
296DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
297DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));
298DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));
299}
300DBG("\n");
301}
302
303//-------------------------------------------------------------------------------------------------------------------------
304// MemoryDevice
305//-------------------------------------------------------------------------------------------------------------------------
306-(void) decodeMemoryDevice:(SMBMemoryDevice *) structHeader
307{
308NSDictionary* memDict = [NSDictionary dictionaryWithObjects:
309 [NSArray arrayWithObjects: SHVAL2(deviceLocator, bankLocator),
310 [NSString stringWithUTF8String: SMBMemoryDeviceTypes[structHeader->memoryType]], nil ]
311 forKeys: [NSArray arrayWithObjects:@"Device Locator", @"Bank Locator", @"Memory Type", nil]];
312
313NSDictionary* extmemDict = (structHeader->header.length < 27) ? nil :
314[NSDictionary dictionaryWithObjects:
315 [NSArray arrayWithObjects: MHZ(memorySpeed), SHVAL4(manufacturer, serialNumber, assetTag, partNumber), nil ]
316 forKeys: [NSArray arrayWithObjects:@"Memory Speed", @"Manufacturer", @"Serial Number", @"Asset Tag", @"Part Number", nil]];
317
318NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
319 [NSArray arrayWithObjects: memDict, extmemDict, nil ]
320 forKeys: [NSArray arrayWithObjects:@"Information", @"More Information", nil]];
321ADD_HANDLE(@"Memory Device");
322
323DBG("MemoryDevice:\n");
324DBG("\tdeviceLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->deviceLocator));
325DBG("\tbankLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->bankLocator));
326DBG("\tmemoryType: %s\n", SMBMemoryDeviceTypes[structHeader->memoryType]);
327
328if (structHeader->header.length < 27)
329{
330DBG("\n");
331return;
332}
333
334DBG("\tmemorySpeed: %dMHz\n", structHeader->memorySpeed);
335DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
336DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
337DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));
338DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));
339DBG("\n");
340}
341
342//-------------------------------------------------------------------------------------------------------------------------
343// Apple Specific
344//-------------------------------------------------------------------------------------------------------------------------
345-(void) decodeOemProcessorType:(SMBOemProcessorType *)structHeader
346{
347NSDictionary* innerDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: SHVAL(ProcessorType), nil ]
348 forKeys: [NSArray arrayWithObjects:@"Processor Type", nil]];
349ADD_HANDLE(@"Apple Processor Type");
350
351DBG("AppleProcessorType:\n");
352DBG("\tProcessorType: 0x%x\n", ((SMBOemProcessorType *)structHeader)->ProcessorType);
353DBG("\n");
354}
355
356-(void) decodeOemProcessorBusSpeed:(SMBOemProcessorBusSpeed *)structHeader
357{
358NSString * qpi = [NSString stringWithFormat:@"%d.%d GT/s",
359 ((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000,
360 (((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10];
361NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
362 [NSArray arrayWithObjects: qpi, nil ] forKeys: [NSArray arrayWithObjects:@"Bus Speed (QPI)", nil]];
363ADD_HANDLE(@"Apple Processor Bus Speed");
364
365DBG("AppleProcessorBusSpeed:\n");
366DBG("\tProcessorBusSpeed (QPI): %d.%dGT/s\n",
367((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000,
368(((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10);
369DBG("\n");
370}
371//-------------------------------------------------------------------------------------------------------------------------
372
373
374-(void) decodeSMBIOSTableFrom:(uint8_t *) ptr to: (uint8_t*) end
375{
376DBG("\n");
377for (SMBStructHeader *structHeader = (SMBStructHeader*)ptr; structHeader < (SMBStructHeader*)end ;)
378{
379// DBG("Type: %d, Length: %d, Handle: 0x%x\n", structHeader->type, structHeader->length, structHeader->handle);
380switch (structHeader->type)
381{
382case kSMBTypeBIOSInformation:
383[self decodeBIOSInformation: (SMBBIOSInformation *) structHeader];
384break;
385
386case kSMBTypeSystemInformation:
387[self decodeSystemInformation: (SMBSystemInformation *)structHeader];
388break;
389
390case kSMBTypeBaseBoard:
391[self decodeBaseBoard: (SMBBaseBoard *)structHeader];
392break;
393
394case kSMBTypeSystemEnclosure:
395[self decodeSystemEnclosure:(SMBSystemEnclosure *)structHeader];
396break;
397
398case kSMBTypeProcessorInformation:
399[self decodeProcessorInformation:(SMBProcessorInformation *)structHeader];
400break;
401
402case kSMBTypeMemoryDevice:
403[self decodeMemoryDevice:(SMBMemoryDevice *)structHeader];
404break;
405
406case kSMBTypeOemProcessorType:
407[self decodeOemProcessorType:(SMBOemProcessorType *)structHeader];
408break;
409
410case kSMBTypeOemProcessorBusSpeed:
411[self decodeOemProcessorBusSpeed:(SMBOemProcessorBusSpeed *)structHeader];
412break;
413
414case kSMBTypeEndOfTable:/* Skip, to be added at the end */
415/* Skip all Apple Specific Structures */
416case kSMBTypeFirmwareVolume:
417case kSMBTypeMemorySPD:
418default:
419break;
420}
421
422ptr = (uint8_t*) (((unsigned long)structHeader) + structHeader->length);
423for (; ((uint16_t *)ptr)[0] != 0; ptr++);
424
425if (((uint16_t *)ptr)[0] == 0)
426ptr += 2;
427
428structHeader = (SMBStructHeader *)ptr;
429}
430DBG("\n");
431}
432
433
434
435@end
436

Archive Download this file

Revision: 382