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