Chameleon Applications

Chameleon Applications Svn Source Tree

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

Archive Download this file

Revision: 396