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