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