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