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