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