]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Library/Library.c
Assert() break point default is DEADLOOP().
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Library / Library.c
CommitLineData
797a9d67 1/**@file\r
2 DXE Core library services.\r
3 \r
4Copyright (c) 2006 - 2007, Intel Corporation\r
28a00297 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
797a9d67 13**/\r
28a00297 14\r
15#include <DxeMain.h>\r
16\r
17UINTN mErrorLevel = EFI_D_ERROR | EFI_D_LOAD;\r
18\r
797a9d67 19EFI_DXE_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = {\r
28a00297 20 {\r
21 sizeof (EFI_STATUS_CODE_DATA),\r
22 0,\r
797a9d67 23 EFI_STATUS_CODE_DXE_CORE_GUID\r
28a00297 24 },\r
25 NULL\r
26};\r
27\r
28VOID\r
29CoreReportProgressCodeSpecific (\r
30 IN EFI_STATUS_CODE_VALUE Value,\r
31 IN EFI_HANDLE Handle\r
32 )\r
33/*++\r
34\r
35Routine Description:\r
36\r
eba54e17 37 Report status code of type EFI_PROGRESS_CODE by caller ID gEfiCallerIdGuid,\r
28a00297 38 with a handle as additional information.\r
39\r
40Arguments:\r
41\r
42 Value - Describes the class/subclass/operation of the hardware or software entity\r
43 that the Status Code relates to.\r
44\r
45 Handle - Additional information.\r
46\r
47Returns:\r
48\r
49 None\r
50\r
51--*/\r
52{\r
797a9d67 53 mStatusCodeData.DataHeader.Size = sizeof (EFI_DXE_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA);\r
28a00297 54 mStatusCodeData.Handle = Handle;\r
55\r
56 if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {\r
57 gStatusCode->ReportStatusCode (\r
58 EFI_PROGRESS_CODE,\r
59 Value,\r
60 0,\r
eba54e17 61 &gEfiCallerIdGuid,\r
28a00297 62 (EFI_STATUS_CODE_DATA *) &mStatusCodeData\r
63 );\r
64 }\r
65}\r
66\r
67VOID\r
68CoreReportProgressCode (\r
69 IN EFI_STATUS_CODE_VALUE Value\r
70 )\r
71/*++\r
72\r
73Routine Description:\r
74\r
eba54e17 75 Report status code of type EFI_PROGRESS_CODE by caller ID gEfiCallerIdGuid.\r
28a00297 76\r
77Arguments:\r
78\r
79 Value - Describes the class/subclass/operation of the hardware or software entity\r
80 that the Status Code relates to.\r
81\r
82Returns:\r
83\r
84 None\r
85\r
86--*/\r
87{\r
88 if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {\r
89 gStatusCode->ReportStatusCode (\r
90 EFI_PROGRESS_CODE,\r
91 Value,\r
92 0,\r
eba54e17 93 &gEfiCallerIdGuid,\r
28a00297 94 NULL\r
95 );\r
96 }\r
97}\r
98\r
99\r
100VOID *\r
101CoreAllocateBootServicesPool (\r
102 IN UINTN AllocationSize\r
103 )\r
104/*++\r
105\r
106Routine Description:\r
107\r
108 Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.\r
109\r
110Arguments:\r
111\r
112 AllocationSize - Size to allocate.\r
113\r
114Returns:\r
115\r
116 Pointer of the allocated pool.\r
117\r
118--*/\r
119{\r
120 VOID *Memory;\r
121\r
122 CoreAllocatePool (EfiBootServicesData, AllocationSize, &Memory);\r
123 return Memory;\r
124}\r
125\r
126\r
127VOID *\r
128CoreAllocateZeroBootServicesPool (\r
129 IN UINTN AllocationSize\r
130 )\r
131/*++\r
132\r
133Routine Description:\r
134\r
135 Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.\r
136\r
137Arguments:\r
138\r
139 AllocationSize - Size to allocate.\r
140\r
141Returns:\r
142\r
143 Pointer of the allocated pool.\r
144\r
145--*/\r
146{\r
147 VOID *Memory;\r
148\r
149 Memory = CoreAllocateBootServicesPool (AllocationSize);\r
150 SetMem (Memory, (Memory == NULL) ? 0 : AllocationSize, 0);\r
151 return Memory;\r
152}\r
153\r
154\r
155VOID *\r
156CoreAllocateCopyPool (\r
157 IN UINTN AllocationSize,\r
158 IN VOID *Buffer\r
159 )\r
160/*++\r
161\r
162Routine Description:\r
163\r
164 Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.\r
165\r
166Arguments:\r
167\r
168 AllocationSize - Size to allocate.\r
169\r
170 Buffer - Specified buffer that will be copy to the allocated pool\r
171\r
172Returns:\r
173\r
174 Pointer of the allocated pool.\r
175\r
176--*/\r
177{\r
178 VOID *Memory;\r
179\r
180 Memory = CoreAllocateBootServicesPool (AllocationSize);\r
181 CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);\r
182\r
183 return Memory;\r
184}\r
185\r
186\r
187\r
188VOID *\r
189CoreAllocateRuntimePool (\r
190 IN UINTN AllocationSize\r
191 )\r
192/*++\r
193\r
194Routine Description:\r
195\r
196 Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.\r
197\r
198Arguments:\r
199\r
200 AllocationSize - Size to allocate.\r
201\r
202Returns:\r
203\r
204 Pointer of the allocated pool.\r
205\r
206--*/\r
207{\r
208 VOID *Memory;\r
209\r
210 CoreAllocatePool (EfiRuntimeServicesData, AllocationSize, &Memory);\r
211 return Memory;\r
212}\r
213\r
214VOID *\r
215CoreAllocateRuntimeCopyPool (\r
216 IN UINTN AllocationSize,\r
217 IN VOID *Buffer\r
218 )\r
219/*++\r
220\r
221Routine Description:\r
222\r
223 Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.\r
224\r
225Arguments:\r
226\r
227 AllocationSize - Size to allocate.\r
228\r
229 Buffer - Specified buffer that will be copy to the allocated pool\r
230\r
231Returns:\r
232\r
233 Pointer of the allocated pool.\r
234\r
235--*/\r
236\r
237{\r
238 VOID *Memory;\r
239\r
240 Memory = CoreAllocateRuntimePool (AllocationSize);\r
241 CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);\r
242\r
243 return Memory;\r
244}\r
245\r
246\r
247\r
248//\r
249// Lock Stuff\r
250//\r
251\r
252\r
253\r
254EFI_STATUS\r
255CoreAcquireLockOrFail (\r
256 IN EFI_LOCK *Lock\r
257 )\r
258/*++\r
259\r
260Routine Description:\r
261\r
262 Initialize a basic mutual exclusion lock. Each lock\r
263 provides mutual exclusion access at it's task priority\r
264 level. Since there is no-premption (at any TPL) or\r
265 multiprocessor support, acquiring the lock only consists\r
266 of raising to the locks TPL.\r
267\r
268Arguments:\r
269\r
270 Lock - The EFI_LOCK structure to initialize\r
271\r
272Returns:\r
273\r
274 EFI_SUCCESS - Lock Owned.\r
275 EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.\r
276\r
277--*/\r
278{\r
279 ASSERT (Lock != NULL);\r
280 ASSERT (Lock->Lock != EfiLockUninitialized);\r
281\r
282 if (Lock->Lock == EfiLockAcquired) {\r
283 //\r
284 // Lock is already owned, so bail out\r
285 //\r
286 return EFI_ACCESS_DENIED;\r
287 }\r
288\r
289 Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);\r
290\r
291 Lock->Lock = EfiLockAcquired;\r
292 return EFI_SUCCESS;\r
293}\r
294\r
295\r
296VOID\r
297CoreAcquireLock (\r
298 IN EFI_LOCK *Lock\r
299 )\r
300/*++\r
301\r
302Routine Description:\r
303\r
304 Raising to the task priority level of the mutual exclusion\r
305 lock, and then acquires ownership of the lock.\r
306\r
307Arguments:\r
308\r
309 Lock - The lock to acquire\r
310\r
311Returns:\r
312\r
313 Lock owned\r
314\r
315--*/\r
316{\r
317 ASSERT (Lock != NULL);\r
318 ASSERT (Lock->Lock == EfiLockReleased);\r
319\r
320 Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);\r
321 Lock->Lock = EfiLockAcquired;\r
322}\r
323\r
324\r
325VOID\r
326CoreReleaseLock (\r
327 IN EFI_LOCK *Lock\r
328 )\r
329/*++\r
330\r
331Routine Description:\r
332\r
333 Releases ownership of the mutual exclusion lock, and\r
334 restores the previous task priority level.\r
335\r
336Arguments:\r
337\r
338 Lock - The lock to release\r
339\r
340Returns:\r
341\r
342 Lock unowned\r
343\r
344--*/\r
345{\r
346 EFI_TPL Tpl;\r
347\r
348 ASSERT (Lock != NULL);\r
349 ASSERT (Lock->Lock == EfiLockAcquired);\r
350\r
351 Tpl = Lock->OwnerTpl;\r
352\r
353 Lock->Lock = EfiLockReleased;\r
354\r
355 CoreRestoreTpl (Tpl);\r
356}\r
357\r
358\r
359UINTN\r
360CoreDevicePathSize (\r
361 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
362 )\r
363/*++\r
364\r
365Routine Description:\r
366\r
367 Calculate the size of a whole device path.\r
368\r
369Arguments:\r
370\r
371 DevicePath - The pointer to the device path data.\r
372\r
373Returns:\r
374\r
375 Size of device path data structure..\r
376\r
377--*/\r
378{\r
379 EFI_DEVICE_PATH_PROTOCOL *Start;\r
380\r
381 if (DevicePath == NULL) {\r
382 return 0;\r
383 }\r
384\r
385 //\r
386 // Search for the end of the device path structure\r
387 //\r
388 Start = DevicePath;\r
389 while (!EfiIsDevicePathEnd (DevicePath)) {\r
390 DevicePath = EfiNextDevicePathNode (DevicePath);\r
391 }\r
392\r
393 //\r
394 // Compute the size and add back in the size of the end device path structure\r
395 //\r
396 return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
397}\r
398\r
399\r
400BOOLEAN\r
401CoreIsDevicePathMultiInstance (\r
402 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
403 )\r
404/*++\r
405\r
406Routine Description:\r
407 Return TRUE is this is a multi instance device path.\r
408\r
409Arguments:\r
410 DevicePath - A pointer to a device path data structure.\r
411\r
412\r
413Returns:\r
414 TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi\r
415 instance.\r
416\r
417--*/\r
418{\r
419 EFI_DEVICE_PATH_PROTOCOL *Node;\r
420\r
421 if (DevicePath == NULL) {\r
422 return FALSE;\r
423 }\r
424\r
425 Node = DevicePath;\r
426 while (!EfiIsDevicePathEnd (Node)) {\r
427 if (EfiIsDevicePathEndInstance (Node)) {\r
428 return TRUE;\r
429 }\r
430 Node = EfiNextDevicePathNode (Node);\r
431 }\r
432 return FALSE;\r
433}\r
434\r
435\r
436\r
437EFI_DEVICE_PATH_PROTOCOL *\r
438CoreDuplicateDevicePath (\r
439 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
440 )\r
441/*++\r
442\r
443Routine Description:\r
444 Duplicate a new device path data structure from the old one.\r
445\r
446Arguments:\r
447 DevicePath - A pointer to a device path data structure.\r
448\r
449Returns:\r
450 A pointer to the new allocated device path data.\r
451 Caller must free the memory used by DevicePath if it is no longer needed.\r
452\r
453--*/\r
454{\r
455 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
456 UINTN Size;\r
457\r
458 if (DevicePath == NULL) {\r
459 return NULL;\r
460 }\r
461\r
462 //\r
463 // Compute the size\r
464 //\r
465 Size = CoreDevicePathSize (DevicePath);\r
466\r
467 //\r
468 // Allocate space for duplicate device path\r
469 //\r
470 NewDevicePath = CoreAllocateCopyPool (Size, DevicePath);\r
471\r
472 return NewDevicePath;\r
473}\r
474\r
475\r
476\r
477EFI_DEVICE_PATH_PROTOCOL *\r
478CoreAppendDevicePath (\r
479 IN EFI_DEVICE_PATH_PROTOCOL *Src1,\r
480 IN EFI_DEVICE_PATH_PROTOCOL *Src2\r
481 )\r
482/*++\r
483\r
484Routine Description:\r
485 Function is used to append a Src1 and Src2 together.\r
486\r
487Arguments:\r
488 Src1 - A pointer to a device path data structure.\r
489\r
490 Src2 - A pointer to a device path data structure.\r
491\r
492Returns:\r
493\r
494 A pointer to the new device path is returned.\r
495 NULL is returned if space for the new device path could not be allocated from pool.\r
496 It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.\r
497\r
498--*/\r
499{\r
500 UINTN Size;\r
501 UINTN Size1;\r
502 UINTN Size2;\r
503 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
504 EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath;\r
505\r
506 if (Src1 == NULL && Src2 == NULL) {\r
507 return NULL;\r
508 }\r
509\r
510 //\r
511 // Allocate space for the combined device path. It only has one end node of\r
512 // length EFI_DEVICE_PATH_PROTOCOL\r
513 //\r
514 Size1 = CoreDevicePathSize (Src1);\r
515 Size2 = CoreDevicePathSize (Src2);\r
516 Size = Size1 + Size2 - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
517\r
518 NewDevicePath = CoreAllocateCopyPool (Size, Src1);\r
519 if (NewDevicePath != NULL) {\r
520\r
521 //\r
522 // Over write Src1 EndNode and do the copy\r
523 //\r
524 SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL)));\r
525 CopyMem (SecondDevicePath, Src2, Size2);\r
526 }\r
527\r
528 return NewDevicePath;\r
529}\r
530\r
531\r
532\r
533EFI_EVENT\r
534CoreCreateProtocolNotifyEvent (\r
535 IN EFI_GUID *ProtocolGuid,\r
536 IN EFI_TPL NotifyTpl,\r
537 IN EFI_EVENT_NOTIFY NotifyFunction,\r
538 IN VOID *NotifyContext,\r
539 OUT VOID **Registration,\r
540 IN BOOLEAN SignalFlag\r
541 )\r
542/*++\r
543\r
544Routine Description:\r
545\r
546 Create a protocol notification event and return it.\r
547\r
548Arguments:\r
549\r
550 ProtocolGuid - Protocol to register notification event on.\r
551\r
552 NotifyTpl - Maximum TPL to signal the NotifyFunction.\r
553\r
554 NotifyFuncition - EFI notification routine.\r
555\r
556 NotifyContext - Context passed into Event when it is created.\r
557\r
558 Registration - Registration key returned from RegisterProtocolNotify().\r
559\r
560 SignalFlag - Boolean value to decide whether kick the event after register or not.\r
561\r
562Returns:\r
563\r
564 The EFI_EVENT that has been registered to be signaled when a ProtocolGuid\r
565 is added to the system.\r
566\r
567--*/\r
568{\r
569 EFI_STATUS Status;\r
570 EFI_EVENT Event;\r
571\r
572 //\r
573 // Create the event\r
574 //\r
575\r
576 Status = CoreCreateEvent (\r
577 EVT_NOTIFY_SIGNAL,\r
578 NotifyTpl,\r
579 NotifyFunction,\r
580 NotifyContext,\r
581 &Event\r
582 );\r
583 ASSERT_EFI_ERROR (Status);\r
584\r
585 //\r
586 // Register for protocol notifactions on this event\r
587 //\r
588\r
589 Status = CoreRegisterProtocolNotify (\r
590 ProtocolGuid,\r
591 Event,\r
592 Registration\r
593 );\r
594 ASSERT_EFI_ERROR (Status);\r
595\r
596 if (SignalFlag) {\r
597 //\r
598 // Kick the event so we will perform an initial pass of\r
599 // current installed drivers\r
600 //\r
601 CoreSignalEvent (Event);\r
602 }\r
603\r
604 return Event;\r
605}\r
606\r