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