]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/MiscSubClassPlatformDxe/MiscSubclassDriverEntryPoint.c
clean up
[mirror_edk2.git] / Nt32Pkg / MiscSubClassPlatformDxe / MiscSubclassDriverEntryPoint.c
CommitLineData
8879d432 1/*++\r
2\r
3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 MiscSubclassDriverEntryPoint.c\r
15\r
16Abstract:\r
17\r
18 This driver parses the mMiscSubclassDataTable structure and reports\r
19 any generated data to the DataHub.\r
20\r
21--*/\r
22\r
23//\r
24// Include common header file for this module.\r
25//\r
26#include "CommonHeader.h"\r
27\r
28#include "MiscSubclassDriver.h"\r
29\r
30\r
31extern UINT8 MiscSubclassStrings[];\r
32\r
33VOID\r
34EFIAPI\r
35WinNtIoProtocolNotifyFunction (\r
36 IN EFI_EVENT Event,\r
37 IN VOID *Context\r
38 );\r
39\r
40//\r
41//\r
42//\r
43EFI_STATUS\r
44LogRecordDataToDataHub (\r
45 EFI_DATA_HUB_PROTOCOL *DataHub,\r
46 UINT32 RecordType,\r
47 UINT32 RecordLen,\r
48 VOID *RecordData\r
49 )\r
50/*++\r
51Description:\r
52\r
53Parameters:\r
54\r
55 DataHub\r
56 %%TBD\r
57\r
58 RecordType\r
59 %%TBD\r
60\r
61 RecordLen\r
62 %%TBD\r
63\r
64 RecordData\r
65 %%TBD\r
66\r
67Returns:\r
68\r
69 EFI_INVALID_PARAMETER\r
70\r
71 EFI_SUCCESS\r
72\r
73 Other Data Hub errors\r
74\r
75--*/\r
76{\r
77 EFI_MISC_SUBCLASS_DRIVER_DATA MiscSubclass;\r
78 EFI_STATUS EfiStatus;\r
79\r
80 //\r
81 // Do nothing if data parameters are not valid.\r
82 //\r
83 if (RecordLen == 0 || RecordData == NULL) {\r
84 DEBUG (\r
85 (EFI_D_ERROR,\r
86 "RecordLen == %d RecordData == %xh\n",\r
87 RecordLen,\r
88 RecordData)\r
89 );\r
90\r
91 return EFI_INVALID_PARAMETER;\r
92 }\r
93 //\r
94 // Assemble Data Hub record.\r
95 //\r
96 MiscSubclass.Header.Version = EFI_MISC_SUBCLASS_VERSION;\r
97 MiscSubclass.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);\r
98 MiscSubclass.Header.Instance = 1;\r
99 MiscSubclass.Header.SubInstance = 1;\r
100 MiscSubclass.Header.RecordType = RecordType;\r
101\r
102 CopyMem (\r
103 &MiscSubclass.Record,\r
104 RecordData,\r
105 RecordLen\r
106 );\r
107\r
108 //\r
109 // Log Data Hub record.\r
110 //\r
111 EfiStatus = DataHub->LogData (\r
112 DataHub,\r
113 &gEfiMiscSubClassGuid,\r
114 &gEfiMiscSubClassGuid,\r
115 EFI_DATA_RECORD_CLASS_DATA,\r
116 &MiscSubclass,\r
117 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen\r
118 );\r
119\r
120 if (EFI_ERROR (EfiStatus)) {\r
121 DEBUG (\r
122 (EFI_D_ERROR,\r
123 "LogData(%d bytes) == %r\n",\r
124 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen,\r
125 EfiStatus)\r
126 );\r
127 }\r
128\r
129 return EfiStatus;\r
130}\r
131\r
132\r
133EFI_STATUS\r
134EFIAPI\r
135MiscSubclassDriverEntryPoint (\r
136 IN EFI_HANDLE ImageHandle,\r
137 IN EFI_SYSTEM_TABLE *SystemTable\r
138 )\r
139/*++\r
140Description:\r
141\r
142 Standard EFI driver point. This driver parses the mMiscSubclassDataTable\r
143 structure and reports any generated data to the DataHub.\r
144\r
145Arguments:\r
146\r
147 ImageHandle\r
148 Handle for the image of this driver\r
149\r
150 SystemTable\r
151 Pointer to the EFI System Table\r
152\r
153Returns:\r
154\r
155 EFI_SUCCESS\r
156 The data was successfully reported to the Data Hub.\r
157\r
158--*/\r
159{\r
160 EFI_MISC_SUBCLASS_DRIVER_DATA RecordData;\r
161 EFI_DATA_HUB_PROTOCOL *DataHub;\r
162 EFI_HII_PROTOCOL *Hii;\r
163 EFI_HII_PACKAGES *PackageList;\r
164 EFI_HII_HANDLE HiiHandle;\r
165 EFI_STATUS EfiStatus;\r
166 UINTN Index;\r
167 BOOLEAN LogRecordData;\r
168 EFI_EVENT Event;\r
169 VOID *Registration;\r
170\r
171\r
172 //\r
173 // Initialize constant portion of subclass header.\r
174 //\r
175 RecordData.Header.Version = EFI_MISC_SUBCLASS_VERSION;\r
176 RecordData.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);\r
177 RecordData.Header.Instance = 1;\r
178 RecordData.Header.SubInstance = 1;\r
179\r
180 //\r
181 // Locate data hub protocol.\r
182 //\r
183 EfiStatus = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);\r
184\r
185 if (EFI_ERROR (EfiStatus)) {\r
186 DEBUG ((EFI_D_ERROR, "Could not locate DataHub protocol. %r\n", EfiStatus));\r
187 return EfiStatus;\r
188 } else if (DataHub == NULL) {\r
189 DEBUG ((EFI_D_ERROR, "LocateProtocol(DataHub) returned NULL pointer!\n"));\r
190 return EFI_DEVICE_ERROR;\r
191 }\r
192 //\r
193 // Locate hii protocol.\r
194 //\r
195 EfiStatus = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii);\r
196\r
197 if (EFI_ERROR (EfiStatus)) {\r
198 DEBUG ((EFI_D_ERROR, "Could not locate Hii protocol. %r\n", EfiStatus));\r
199 return EfiStatus;\r
200 } else if (Hii == NULL) {\r
201 DEBUG ((EFI_D_ERROR, "LocateProtocol(Hii) returned NULL pointer!\n"));\r
202 return EFI_DEVICE_ERROR;\r
203 }\r
204 //\r
205 // Add our default strings to the HII database. They will be modified later.\r
206 //\r
207 PackageList = PreparePackages (1, &gEfiMiscSubClassGuid, MiscSubclassStrings);\r
208 EfiStatus = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
209 FreePool (PackageList);\r
210\r
211 if (EFI_ERROR (EfiStatus)) {\r
212 DEBUG ((EFI_D_ERROR, "Could not log default strings to Hii. %r\n", EfiStatus));\r
213 return EfiStatus;\r
214 }\r
215 //\r
216 //\r
217 //\r
218 for (Index = 0; Index < mMiscSubclassDataTableEntries; ++Index) {\r
219 //\r
220 // Stupidity check! Do nothing if RecordLen is zero.\r
221 // %%TBD - Should this be an error or a mechanism for ignoring\r
222 // records in the Data Table?\r
223 //\r
224 if (mMiscSubclassDataTable[Index].RecordLen == 0) {\r
225 DEBUG (\r
226 (EFI_D_ERROR,\r
227 "mMiscSubclassDataTable[%d].RecordLen == 0\n",\r
228 Index)\r
229 );\r
230\r
231 continue;\r
232 }\r
233 //\r
234 // Initialize per-record portion of subclass header and\r
235 // copy static data into data portion of subclass record.\r
236 //\r
237 RecordData.Header.RecordType = mMiscSubclassDataTable[Index].RecordType;\r
238\r
239 if (mMiscSubclassDataTable[Index].RecordData == NULL) {\r
240 ZeroMem (\r
241 &RecordData.Record,\r
242 mMiscSubclassDataTable[Index].RecordLen\r
243 );\r
244 } else {\r
245 CopyMem (\r
246 &RecordData.Record,\r
247 mMiscSubclassDataTable[Index].RecordData,\r
248 mMiscSubclassDataTable[Index].RecordLen\r
249 );\r
250 }\r
251 //\r
252 // If the entry does not have a function pointer, just log the data.\r
253 //\r
254 if (mMiscSubclassDataTable[Index].Function == NULL) {\r
255 //\r
256 // Log RecordData to Data Hub.\r
257 //\r
258 EfiStatus = DataHub->LogData (\r
259 DataHub,\r
260 &gEfiMiscSubClassGuid,\r
261 &gEfiMiscSubClassGuid,\r
262 EFI_DATA_RECORD_CLASS_DATA,\r
263 &RecordData,\r
264 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen\r
265 );\r
266\r
267 if (EFI_ERROR (EfiStatus)) {\r
268 DEBUG (\r
269 (EFI_D_ERROR,\r
270 "LogData(%d bytes) == %r\n",\r
271 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen,\r
272 EfiStatus)\r
273 );\r
274 }\r
275\r
276 continue;\r
277 }\r
278 //\r
279 // The entry has a valid function pointer.\r
280 // Keep calling the function and logging data until there\r
281 // is no more data to log.\r
282 //\r
283 for (;;) {\r
284 //\r
285 //\r
286 //\r
287 EfiStatus = (*mMiscSubclassDataTable[Index].Function)\r
288 (\r
289 mMiscSubclassDataTable[Index].RecordType, &mMiscSubclassDataTable[Index].RecordLen, &RecordData.Record, &\r
290 LogRecordData\r
291 );\r
292\r
293 //\r
294 //\r
295 //\r
296 if (EFI_ERROR (EfiStatus)) {\r
297 break;\r
298 }\r
299\r
300 if (!LogRecordData) {\r
301 break;\r
302 }\r
303 //\r
304 //\r
305 //\r
306 EfiStatus = DataHub->LogData (\r
307 DataHub,\r
308 &gEfiMiscSubClassGuid,\r
309 &gEfiMiscSubClassGuid,\r
310 EFI_DATA_RECORD_CLASS_DATA,\r
311 &RecordData,\r
312 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen\r
313 );\r
314\r
315 if (EFI_ERROR (EfiStatus)) {\r
316 DEBUG (\r
317 (EFI_D_ERROR,\r
318 "LogData(%d bytes) == %r\n",\r
319 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen,\r
320 EfiStatus)\r
321 );\r
322 }\r
323 }\r
324 }\r
325 //\r
326 // Install notify function to fetch memory data through WinNtIo protocol and store to data hub.\r
327 //\r
328 EfiStatus = gBS->CreateEvent (\r
329 EVT_NOTIFY_SIGNAL,\r
330 TPL_CALLBACK,\r
331 WinNtIoProtocolNotifyFunction,\r
332 ImageHandle,\r
333 &Event\r
334 );\r
335 ASSERT (!EFI_ERROR (EfiStatus));\r
336\r
337 EfiStatus = gBS->RegisterProtocolNotify (\r
338 &gEfiWinNtIoProtocolGuid,\r
339 Event,\r
340 &Registration\r
341 );\r
342 ASSERT (!EFI_ERROR (EfiStatus));\r
343\r
344 return EFI_SUCCESS;\r
345}\r
346\r
347UINTN\r
348Atoi (\r
349 CHAR16 *String\r
350 )\r
351/*++\r
352\r
353Routine Description:\r
354 Convert a unicode string to a UINTN\r
355\r
356Arguments:\r
357 String - Unicode string.\r
358\r
359Returns:\r
360 UINTN of the number represented by String.\r
361\r
362--*/\r
363{\r
364 UINTN Number;\r
365 CHAR16 *Str;\r
366\r
367 //\r
368 // skip preceeding white space\r
369 //\r
370 Str = String;\r
371 while ((*Str) && (*Str == ' ' || *Str == '"')) {\r
372 Str++;\r
373 }\r
374 //\r
375 // Convert ot a Number\r
376 //\r
377 Number = 0;\r
378 while (*Str != '\0') {\r
379 if ((*Str >= '0') && (*Str <= '9')) {\r
380 Number = (Number * 10) +*Str - '0';\r
381 } else {\r
382 break;\r
383 }\r
384\r
385 Str++;\r
386 }\r
387\r
388 return Number;\r
389}\r
390\r
391VOID\r
392EFIAPI\r
393WinNtIoProtocolNotifyFunction (\r
394 IN EFI_EVENT Event,\r
395 IN VOID *Context\r
396 )\r
397/*++\r
398\r
399Routine Description:\r
400 This function will log memory size data to data hub.\r
401\r
402Arguments:\r
403Event - Event whose notification function is being invoked.\r
404Context - Pointer to the notification function's context.\r
405\r
406Returns:\r
407 EFI_STATUS.\r
408\r
409--*/\r
410{\r
411 EFI_STATUS Status;\r
412 EFI_MEMORY_SUBCLASS_DRIVER_DATA MemorySubClassData;\r
413 EFI_DATA_RECORD_HEADER *Record;\r
414 EFI_SUBCLASS_TYPE1_HEADER *DataHeader;\r
415 UINTN HandleCount;\r
416 UINTN HandleIndex;\r
417 UINT64 MonotonicCount;\r
418 BOOLEAN RecordFound;\r
419 EFI_HANDLE *HandleBuffer;\r
420 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
421 EFI_DATA_HUB_PROTOCOL *DataHub;\r
422 UINT64 TotalMemorySize;\r
423\r
424 DataHub = NULL;\r
425 MonotonicCount = 0;\r
426 RecordFound = FALSE;\r
427\r
428 //\r
429 // Retrieve the list of all handles from the handle database.\r
430 //\r
431 Status = gBS->LocateHandleBuffer (\r
432 AllHandles,\r
433 &gEfiWinNtIoProtocolGuid,\r
434 NULL,\r
435 &HandleCount,\r
436 &HandleBuffer\r
437 );\r
438 if (EFI_ERROR (Status)) {\r
439 return ;\r
440 }\r
441 //\r
442 // Locate DataHub protocol.\r
443 //\r
444 Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);\r
445 if (EFI_ERROR (Status)) {\r
446 return ;\r
447 }\r
448 //\r
449 // Search the Handle array to find the meory size information.\r
450 //\r
451 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
452 Status = gBS->OpenProtocol (\r
453 HandleBuffer[HandleIndex],\r
454 &gEfiWinNtIoProtocolGuid,\r
455 &WinNtIo,\r
456 Context,\r
457 NULL,\r
458 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
459 );\r
460 if (EFI_ERROR (Status)) {\r
461 continue;\r
462 }\r
463\r
464 if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) &&\r
465 CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtMemoryGuid)\r
466 ) {\r
467 //\r
468 // Check if this record has been stored in data hub.\r
469 //\r
470 do {\r
471 Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
472 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
473 DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
474 if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
475 (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)\r
476 ) {\r
477 RecordFound = TRUE;\r
478 }\r
479 }\r
480 } while (MonotonicCount != 0);\r
481\r
482 if (RecordFound) {\r
483 RecordFound = FALSE;\r
484 continue;\r
485 }\r
486 //\r
487 // Initialize data record.\r
488 //\r
489 MemorySubClassData.Header.Instance = 1;\r
490 MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;\r
491 MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER;\r
492\r
493 TotalMemorySize = (UINT64) Atoi (WinNtIo->EnvString);\r
494\r
495 MemorySubClassData.Record.ArrayStartAddress.MemoryArrayStartAddress = 0;\r
496 MemorySubClassData.Record.ArrayStartAddress.MemoryArrayEndAddress = LShiftU64 (TotalMemorySize, 20) - 1;\r
497 MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemoryProducerGuid;\r
498 MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.Instance = 1;\r
499 MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;\r
500 MemorySubClassData.Record.ArrayStartAddress.MemoryArrayPartitionWidth = 0;\r
501\r
502 //\r
503 // Store memory size data record to data hub.\r
504 //\r
505 Status = DataHub->LogData (\r
506 DataHub,\r
507 &gEfiMemorySubClassGuid,\r
508 &gEfiMemoryProducerGuid,\r
509 EFI_DATA_RECORD_CLASS_DATA,\r
510 &MemorySubClassData,\r
511 sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_START_ADDRESS_DATA)\r
512 );\r
513 }\r
514\r
515 gBS->CloseProtocol (\r
516 HandleBuffer[HandleIndex],\r
517 &gEfiWinNtIoProtocolGuid,\r
518 Context,\r
519 NULL\r
520 );\r
521 }\r
522}\r
523\r