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