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#import "PreferencesControllerBase.h"
10#include "ShellProcess.h"
11#include "string_util.h"
12#include "smbios.h"
13#include "PropertyList.h"
14#include "smbios.h"
15
16#include <stdio.h>
17
18#ifndef DEBUG_SMBIOS
19#define DEBUG_SMBIOS 0
20#endif
21#if 0
22#define DBG(x...)printf(x)
23#else
24#define DBG(x...)
25#endif
26static SMBWord minorVersion;
27
28static char* getSMBStringForField(SMBStructHeader *structHeader, uint8_t field)
29{
30uint8_t *stringPtr = ((uint8_t *)structHeader) + structHeader->length;
31static char empty[2] = "";
32if (!field)
33return empty;
34
35 for (field--; field != 0 && strlen((char *)stringPtr) > 0;
36 field--, stringPtr = (uint8_t *)((unsigned long )stringPtr + strlen((char *)stringPtr) + 1));
37
38return ( char*) (stringPtr ? (char*) stringPtr : empty);
39}
40
41#define SHVAL(field) [NSString stringWithUTF8String: getSMBStringForField((SMBStructHeader *)structHeader, structHeader->field)]
42#define SHVAL2(f,g) SHVAL(f),SHVAL(g)
43#define SHVAL3(f,g,h) SHVAL2(f,g),SHVAL(h)
44#define SHVAL4(f,g,h,i) SHVAL2(f,g),SHVAL2(h,i)
45#define SHVAL5(f,g,h,i,j) SHVAL4(f,g,h,i),SHVAL(j)
46#define SHVAL6(f,g,h,i,j,k) SHVAL5(f,g,h,i,j),SHVAL(k)
47#define SHVAL7(f,g,h,i,j,k,l) SHVAL6(f,g,h,i,j,k),SHVAL(l)
48
49#define MHZ(f) [NSString stringWithFormat:@"%d MHZ", (int)structHeader->f]
50#define DEC(f) [NSString stringWithFormat:@"%d", (int)structHeader->f]
51#define LLX(f) [NSString stringWithFormat:@"%llX", structHeader->f]
52#define HEX32(f) [NSString stringWithFormat:@"0x%08X", (int)structHeader->f]
53#define HEX16(f) [NSString stringWithFormat:@"0x%04X", (int)structHeader->f]
54#define HEX8(f) [NSString stringWithFormat:@"%0x02X", (int)structHeader->f]
55
56@implementation SmbiosExtractor
57
58@synthesize content;
59@synthesize smString;
60@synthesize bufSize;
61-(id) init
62{
63self = [super init];
64if (self!=nil)
65{
66[ self extractSmBios];
67}
68
69return self;
70}
71
72-(void) cleanup
73{
74if (buffer!=nil)
75{
76delete [] buffer;
77buffer = nil;
78bufSize=0;
79smString = nil;
80}
81
82if (smString!=nil)
83{
84[smString release];
85smString = nil;
86}
87
88if (content!=nil)
89{
90[content release];
91content = nil;
92}
93}
94
95-(void) dealloc
96{
97[self cleanup ];
98[super dealloc];
99}
100
101-(NSString*) description
102{
103return [content description];
104}
105
106-(NSUInteger) extractSmBios
107{
108
109const char* SmbiosCmd = "ioreg -lw0 | grep \"\\\"SMBIOS\\\" = <\"";
110const char* SmbiosTag = "\"SMBIOS\" = <";
111ShellProcess p(SmbiosCmd);
112char line[8192]="";
113const size_t tagLen= strlen(SmbiosTag);
114
115if (p.get_line(line, sizeof(line)) )
116{
117const char * p = strstr(line, SmbiosTag)+ tagLen;
118std::string s = trim(p, " \t\r\n>");
119
120// NSLog(@"Found SMBIOS (%d) [%s]", s.length(), s.c_str() );
121
122[self cleanup];
123
124self.content = [NSMutableDictionary dictionaryWithCapacity:32];
125
126self.smString = [NSString stringWithUTF8String:s.c_str()];
127bufSize = s.length()/2;
128buffer = new UInt8[bufSize];
129
130for(size_t pos =0; pos < bufSize; pos++)
131{
132buffer[pos] = (HexToDec(s[pos*2])*16 + HexToDec(s[pos*2+1]));
133}
134
135[self decodeSMBIOSTableFrom:buffer to: buffer+bufSize];
136}
137
138return 0;
139}
140
141-(NSString*) stringFrom:(NSUInteger) start withLen:(NSUInteger) len
142{
143return [smString substringWithRange: NSMakeRange(start*2, len) ];
144}
145
146-(UInt8) ByteFrom:(NSUInteger) position
147{
148return position < bufSize ? buffer[position]: 0;
149}
150
151-(BOOL) save:(NSString*) path
152{
153NSString * error;
154id plist = [NSPropertyListSerialization dataFromPropertyList:(id)content
155 format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
156NSFileManager* fm = [NSFileManager defaultManager];
157NSError* err;
158NSString * dir = [[ path stringByDeletingLastPathComponent] stringByExpandingTildeInPath];
159[fm createDirectoryAtPath:dir withIntermediateDirectories: NO attributes: nil error:&err];
160NSLog(@"Writing Apple SMBIOS to %@", path);
161return [plist writeToFile:[path stringByExpandingTildeInPath] atomically:YES];
162}
163
164#define ADD_HANDLE(text) [content setValue:innerDict forKey: [NSString stringWithFormat:@"%@ (0x%02x)", text, (int) structHeader->header.handle] ]
165//-------------------------------------------------------------------------------------------------------------------------
166// BIOSInformation
167//-------------------------------------------------------------------------------------------------------------------------
168-(void) decodeBIOSInformation:(SMBBIOSInformation *)structHeader
169{
170NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
171[NSArray arrayWithObjects: SHVAL3(vendor, version, releaseDate), nil ]
172 forKeys: [NSArray arrayWithObjects:@"Vendor", @"Version", @"Release Date", nil]];
173
174ADD_HANDLE(@"BIOS Information");
175
176DBG("BIOSInformation:\n");
177DBG("\tvendor: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->vendor));
178DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
179DBG("\treleaseDate: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->releaseDate));
180DBG("\n");
181}
182
183//-------------------------------------------------------------------------------------------------------------------------
184// SystemInformation
185//-------------------------------------------------------------------------------------------------------------------------
186-(void) decodeSystemInformation:(SMBSystemInformation *)structHeader
187{
188NSDictionary* innerDict =
189[NSDictionary dictionaryWithObjects:
190[NSArray arrayWithObjects: SHVAL4(manufacturer, productName, version, serialNumber), nil ]
191forKeys: [NSArray arrayWithObjects:@"Manufacturer", @"Product Name", @"Version", @"Serial Number", nil]];
192
193ADD_HANDLE(@"System Information");
194
195DBG("SystemInformation:\n");
196DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
197DBG("\tproductName: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->productName));
198DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
199DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
200
201if (minorVersion < 1 || structHeader->header.length < 25)
202{
203DBG("\n");
204return;
205}
206uint8_t *uuid = structHeader->uuid;
207DBG("\tuuid: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02x%02X-%02X%02X%02X%02X%02X%02X\n",
208uuid[0], uuid[1], uuid[2], uuid[3],
209uuid[4], uuid[5],
210uuid[6], uuid[7],
211uuid[8], uuid[9],
212uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
213DBG("\twakeupReason: 0x%x\n", structHeader->wakeupReason);
214
215if (minorVersion < 4 || structHeader->header.length < 27)
216{
217DBG("\n");
218return;
219}
220DBG("\tskuNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->skuNumber));
221DBG("\tfamily: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->family));
222DBG("\n");
223}
224
225//-------------------------------------------------------------------------------------------------------------------------
226// BaseBoard
227//-------------------------------------------------------------------------------------------------------------------------
228-(void) decodeBaseBoard:(SMBBaseBoard *) structHeader
229{
230NSDictionary* innerDict =
231[NSDictionary dictionaryWithObjects:
232 [NSArray arrayWithObjects: SHVAL7(manufacturer, product, version, serialNumber, assetTagNumber, locationInChassis, boardType), nil ]
233forKeys: [NSArray arrayWithObjects:@"Manufacturer", @"Product", @"Version", @"Serial Number",
234 @"Asset Tag Number", @"Location In Chassis", @"Board Type", nil]];
235
236ADD_HANDLE(@"Base Board");
237
238DBG("BaseBoard:\n");
239DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
240DBG("\tproduct: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->product));
241DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
242DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
243DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));
244DBG("\tlocationInChassis: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->locationInChassis));
245DBG("\tboardType: 0x%X\n", structHeader->boardType);
246DBG("\n");
247}
248
249//-------------------------------------------------------------------------------------------------------------------------
250// SystemEnclosure
251//-------------------------------------------------------------------------------------------------------------------------
252-(void) decodeSystemEnclosure:(SMBSystemEnclosure *) structHeader
253{
254NSDictionary* innerDict =
255[NSDictionary dictionaryWithObjects:
256 [NSArray arrayWithObjects: SHVAL5(manufacturer, type, version, serialNumber, assetTagNumber), nil ]
257forKeys: [NSArray arrayWithObjects:@"Manufacturer", @"Type", @"Version", @"Serial Number", @"Asset Tag Number", nil]];
258
259ADD_HANDLE(@"System Enclosure");
260
261DBG("SystemEnclosure:\n");
262DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
263DBG("\ttype: %d\n", structHeader->type);
264DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));
265DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
266DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));
267DBG("\n");
268}
269
270//-------------------------------------------------------------------------------------------------------------------------
271// ProcessorInformation
272//-------------------------------------------------------------------------------------------------------------------------
273-(void) decodeProcessorInformation:(SMBProcessorInformation *) structHeader
274{
275NSDictionary* clockDict = [NSDictionary dictionaryWithObjects:
276 [NSArray arrayWithObjects: MHZ(externalClock), MHZ(maximumClock), MHZ(currentClock), nil ]
277forKeys: [NSArray arrayWithObjects:@"External", @"Maximum", @"Current", nil]];
278
279NSDictionary* procDict = [NSDictionary dictionaryWithObjects:
280 [NSArray arrayWithObjects: SHVAL(socketDesignation), DEC(processorType), HEX16(processorFamily), SHVAL(manufacturer),
281 LLX(processorID), SHVAL(processorVersion), nil ]
282forKeys: [NSArray arrayWithObjects:@"Socket", @"Type", @"Family", @"Manufacturer", @"ID", @"Version", nil]];
283
284NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
285 [NSArray arrayWithObjects: procDict, clockDict, nil ]
286forKeys: [NSArray arrayWithObjects:@"Processor", @"Clock", nil]];
287
288ADD_HANDLE(@"Processor Information");
289
290DBG("ProcessorInformation:\n");
291DBG("\tsocketDesignation: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->socketDesignation));
292DBG("\tprocessorType: %d\n", structHeader->processorType);
293DBG("\tprocessorFamily: 0x%X\n", structHeader->processorFamily);
294DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
295DBG("\tprocessorID: 0x%llX\n", structHeader->processorID);
296DBG("\tprocessorVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->processorVersion));
297DBG("\texternalClock: %dMHz\n", structHeader->externalClock);
298DBG("\tmaximumClock: %dMHz\n", structHeader->maximumClock);
299DBG("\tcurrentClock: %dMHz\n", structHeader->currentClock);
300
301if (minorVersion >= 3 && structHeader->header.length >= 35)
302{
303DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
304DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));
305DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));
306}
307DBG("\n");
308}
309
310//-------------------------------------------------------------------------------------------------------------------------
311// MemoryDevice
312//-------------------------------------------------------------------------------------------------------------------------
313-(void) decodeMemoryDevice:(SMBMemoryDevice *) structHeader
314{
315NSDictionary* memDict = [NSDictionary dictionaryWithObjects:
316 [NSArray arrayWithObjects: SHVAL2(deviceLocator, bankLocator),
317 [NSString stringWithUTF8String: SMBMemoryDeviceTypes[structHeader->memoryType]], nil ]
318 forKeys: [NSArray arrayWithObjects:@"Device Locator", @"Bank Locator", @"Memory Type", nil]];
319
320NSDictionary* extmemDict = (structHeader->header.length < 27) ? nil :
321[NSDictionary dictionaryWithObjects:
322 [NSArray arrayWithObjects: MHZ(memorySpeed), SHVAL4(manufacturer, serialNumber, assetTag, partNumber), nil ]
323 forKeys: [NSArray arrayWithObjects:@"Memory Speed", @"Manufacturer", @"Serial Number", @"Asset Tag", @"Part Number", nil]];
324
325NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
326 [NSArray arrayWithObjects: memDict, extmemDict, nil ]
327 forKeys: [NSArray arrayWithObjects:@"Information", @"More Information", nil]];
328ADD_HANDLE(@"Memory Device");
329
330DBG("MemoryDevice:\n");
331DBG("\tdeviceLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->deviceLocator));
332DBG("\tbankLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->bankLocator));
333DBG("\tmemoryType: %s\n", SMBMemoryDeviceTypes[structHeader->memoryType]);
334
335if (structHeader->header.length < 27)
336{
337DBG("\n");
338return;
339}
340
341DBG("\tmemorySpeed: %dMHz\n", structHeader->memorySpeed);
342DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));
343DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));
344DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));
345DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));
346DBG("\n");
347}
348
349//-------------------------------------------------------------------------------------------------------------------------
350// Apple Specific
351//-------------------------------------------------------------------------------------------------------------------------
352-(void) decodeOemProcessorType:(SMBOemProcessorType *)structHeader
353{
354NSDictionary* innerDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: SHVAL(ProcessorType), nil ]
355 forKeys: [NSArray arrayWithObjects:@"Processor Type", nil]];
356ADD_HANDLE(@"Apple Processor Type");
357
358DBG("AppleProcessorType:\n");
359DBG("\tProcessorType: 0x%x\n", ((SMBOemProcessorType *)structHeader)->ProcessorType);
360DBG("\n");
361}
362
363-(void) decodeOemProcessorBusSpeed:(SMBOemProcessorBusSpeed *)structHeader
364{
365NSString * qpi = [NSString stringWithFormat:@"%d.%d GT/s",
366 ((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000,
367 (((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10];
368NSDictionary* innerDict = [NSDictionary dictionaryWithObjects:
369 [NSArray arrayWithObjects: qpi, nil ] forKeys: [NSArray arrayWithObjects:@"Bus Speed (QPI)", nil]];
370ADD_HANDLE(@"Apple Processor Bus Speed");
371
372DBG("AppleProcessorBusSpeed:\n");
373DBG("\tProcessorBusSpeed (QPI): %d.%dGT/s\n",
374((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000,
375(((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10);
376DBG("\n");
377}
378//-------------------------------------------------------------------------------------------------------------------------
379
380
381-(void) decodeSMBIOSTableFrom:(uint8_t *) ptr to: (uint8_t*) end
382{
383DBG("\n");
384for (SMBStructHeader *structHeader = (SMBStructHeader*)ptr; structHeader < (SMBStructHeader*)end ;)
385{
386// DBG("Type: %d, Length: %d, Handle: 0x%x\n", structHeader->type, structHeader->length, structHeader->handle);
387switch (structHeader->type)
388{
389case kSMBTypeBIOSInformation:
390[self decodeBIOSInformation: (SMBBIOSInformation *) structHeader];
391break;
392
393case kSMBTypeSystemInformation:
394[self decodeSystemInformation: (SMBSystemInformation *)structHeader];
395break;
396
397case kSMBTypeBaseBoard:
398[self decodeBaseBoard: (SMBBaseBoard *)structHeader];
399break;
400
401case kSMBTypeSystemEnclosure:
402[self decodeSystemEnclosure:(SMBSystemEnclosure *)structHeader];
403break;
404
405case kSMBTypeProcessorInformation:
406[self decodeProcessorInformation:(SMBProcessorInformation *)structHeader];
407break;
408
409case kSMBTypeMemoryDevice:
410[self decodeMemoryDevice:(SMBMemoryDevice *)structHeader];
411break;
412
413case kSMBTypeOemProcessorType:
414[self decodeOemProcessorType:(SMBOemProcessorType *)structHeader];
415break;
416
417case kSMBTypeOemProcessorBusSpeed:
418[self decodeOemProcessorBusSpeed:(SMBOemProcessorBusSpeed *)structHeader];
419break;
420
421case kSMBTypeEndOfTable:/* Skip, to be added at the end */
422/* Skip all Apple Specific Structures */
423case kSMBTypeFirmwareVolume:
424case kSMBTypeMemorySPD:
425default:
426{
427/*
428NSDictionary* innerDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: nil ] forKeys: [NSArray arrayWithObjects:nil]];
429NSString* title = [NSString stringWithFormat:@"Type %d Len=%d (0x%02x)", (int) structHeader->type, structHeader->length, structHeader->handle];
430[dict setValue:innerDict forKey: title ];
431 */
432}
433break;
434}
435
436ptr = (uint8_t*) (((unsigned long)structHeader) + structHeader->length);
437for (; ((uint16_t *)ptr)[0] != 0; ptr++);
438
439if (((uint16_t *)ptr)[0] == 0)
440ptr += 2;
441
442structHeader = (SMBStructHeader *)ptr;
443}
444DBG("\n");
445}
446
447//-------------------------------------------------------------------------------------------
448// Outline view datasource methods
449//-------------------------------------------------------------------------------------------
450- (int)outlineView:(NSOutlineView *)ov numberOfChildrenOfItem:(id)item
451{
452// this is called with item == nil when asking how many root items there are
453if (item == nil)
454return [self.content count]; // return the number of A's we have
455
456// Here, item will be an A, so we return the count of A's items
457return [[item subitems] count];
458}
459
460//-------------------------------------------------------------------------------------------
461- (BOOL)outlineView:(NSOutlineView *)ov isItemExpandable:(id)item
462{
463// this is called to ask if a particular item has any child items
464// to determine this, we need to know if it is an A which might have some,
465// or a B, which doesn't have any. This will be called to see if numberOfChildrenOfItem
466// should be called on the item passed in to determine how many.
467
468// Ours, only A's are potentially expandable. They also have to have some subitems
469return [item isKindOfClass:[NSDictionary class]] && [[item subitems] count] > 0;
470}
471
472//-------------------------------------------------------------------------------------------
473- (id)outlineView:(NSOutlineView *)ov child:(int)index ofItem:(id)item
474{
475// Here, the outline view is asking for the whole child item. Not values
476// within it yet. In our case, both the single root item (nil) andA's have
477// childs. This is called after asking numberOfChildrenOfItem. Wereturn
478// the children themselves here. When passed nil for item, theoutline view
479// is asking for the root level items
480
481// Asking for A's
482if (item == nil)
483return content;
484
485// Here, item is an A, and it's asking for our B child item at the index
486if ([item isKindOfClass:[NSDictionary class]])
487return [[item subitems] objectAtIndex:index];
488
489// shouldn't get here
490return nil;
491}
492
493//-------------------------------------------------------------------------------------------
494- (id)outlineView:(NSOutlineView *)ov
495objectValueForTableColumn:(NSTableColumn *)tc
496 byItem:(id)item
497{
498// Finally, as the last step, this method is called to get the actual
499// values (or display items) for a instance of A or B
500// You can do special cases based on whether you are passed an A or B
501// or simply make this a one liner by calling return [item valueForKey:[tc identifier]],
502// but both A and B have to have the supporting interfaces implemented the same.
503
504// if there is some difference, or you want to trap different thingsdepending on
505// which class you are passed as item, you can also check here...
506
507if ([item isKindOfClass:[NSDictionary class]])
508{
509// Do something special for A's here to calculate value
510// (I'm getting lazy though)
511return [item valueForKey:[tc identifier]];
512}
513
514// won't get here
515return item;
516}
517@end
518

Archive Download this file

Revision: 386