1 /*++
2
3 Copyright (c) 1998 Intel Corporation
4
5 Module Name:
6
7 hand.c
8
9 Abstract:
10
11
12
13
14 Revision History
15
16 --*/
17
18 #include "lib.h"
19 #include "efistdarg.h" // !!!
20
21
22 EFI_STATUS
LibLocateProtocol(IN EFI_GUID * ProtocolGuid,OUT VOID ** Interface)23 LibLocateProtocol (
24 IN EFI_GUID *ProtocolGuid,
25 OUT VOID **Interface
26 )
27 //
28 // Find the first instance of this Protocol in the system and return it's interface
29 //
30 {
31 EFI_STATUS Status;
32 UINTN NumberHandles, Index;
33 EFI_HANDLE *Handles;
34
35
36 *Interface = NULL;
37 Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles);
38 if (EFI_ERROR(Status)) {
39 DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n"));
40 return Status;
41 }
42
43 for (Index=0; Index < NumberHandles; Index++) {
44 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface);
45 if (!EFI_ERROR(Status)) {
46 break;
47 }
48 }
49
50 if (Handles) {
51 FreePool (Handles);
52 }
53
54 return Status;
55 }
56
57 EFI_STATUS
LibLocateHandle(IN EFI_LOCATE_SEARCH_TYPE SearchType,IN EFI_GUID * Protocol OPTIONAL,IN VOID * SearchKey OPTIONAL,IN OUT UINTN * NoHandles,OUT EFI_HANDLE ** Buffer)58 LibLocateHandle (
59 IN EFI_LOCATE_SEARCH_TYPE SearchType,
60 IN EFI_GUID *Protocol OPTIONAL,
61 IN VOID *SearchKey OPTIONAL,
62 IN OUT UINTN *NoHandles,
63 OUT EFI_HANDLE **Buffer
64 )
65
66 {
67 EFI_STATUS Status;
68 UINTN BufferSize;
69
70 //
71 // Initialize for GrowBuffer loop
72 //
73
74 Status = EFI_SUCCESS;
75 *Buffer = NULL;
76 BufferSize = 50 * sizeof(EFI_HANDLE);
77
78 //
79 // Call the real function
80 //
81
82 while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
83
84 Status = uefi_call_wrapper(
85 BS->LocateHandle,
86 5,
87 SearchType,
88 Protocol,
89 SearchKey,
90 &BufferSize,
91 *Buffer
92 );
93
94 }
95
96 *NoHandles = BufferSize / sizeof (EFI_HANDLE);
97 if (EFI_ERROR(Status)) {
98 *NoHandles = 0;
99 }
100
101 return Status;
102 }
103
104 EFI_STATUS
LibLocateHandleByDiskSignature(IN UINT8 MBRType,IN UINT8 SignatureType,IN VOID * Signature,IN OUT UINTN * NoHandles,OUT EFI_HANDLE ** Buffer)105 LibLocateHandleByDiskSignature (
106 IN UINT8 MBRType,
107 IN UINT8 SignatureType,
108 IN VOID *Signature,
109 IN OUT UINTN *NoHandles,
110 OUT EFI_HANDLE **Buffer
111 )
112
113 {
114 EFI_STATUS Status;
115 UINTN BufferSize;
116 UINTN NoBlockIoHandles;
117 EFI_HANDLE *BlockIoBuffer;
118 EFI_DEVICE_PATH *DevicePath;
119 UINTN Index;
120 EFI_DEVICE_PATH *Next, *DevPath;
121 HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
122 BOOLEAN Match;
123 BOOLEAN PreviousNodeIsHardDriveDevicePath;
124
125 //
126 // Initialize for GrowBuffer loop
127 //
128
129 Status = EFI_SUCCESS;
130 BlockIoBuffer = NULL;
131 BufferSize = 50 * sizeof(EFI_HANDLE);
132
133 //
134 // Call the real function
135 //
136
137 while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
138
139 //
140 // Get list of device handles that support the BLOCK_IO Protocol.
141 //
142
143 Status = uefi_call_wrapper(
144 BS->LocateHandle,
145 5,
146 ByProtocol,
147 &BlockIoProtocol,
148 NULL,
149 &BufferSize,
150 BlockIoBuffer
151 );
152
153 }
154
155 NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
156 if (EFI_ERROR(Status)) {
157 NoBlockIoHandles = 0;
158 }
159
160 //
161 // If there was an error or there are no device handles that support
162 // the BLOCK_IO Protocol, then return.
163 //
164
165 if (NoBlockIoHandles == 0) {
166 FreePool(BlockIoBuffer);
167 *NoHandles = 0;
168 *Buffer = NULL;
169 return Status;
170 }
171
172 //
173 // Loop through all the device handles that support the BLOCK_IO Protocol
174 //
175
176 *NoHandles = 0;
177
178 for(Index=0;Index<NoBlockIoHandles;Index++) {
179
180 Status = uefi_call_wrapper(
181 BS->HandleProtocol,
182 3,
183 BlockIoBuffer[Index],
184 &DevicePathProtocol,
185 (VOID*)&DevicePath
186 );
187
188 //
189 // Search DevicePath for a Hard Drive Media Device Path node.
190 // If one is found, then see if it matches the signature that was
191 // passed in. If it does match, and the next node is the End of the
192 // device path, and the previous node is not a Hard Drive Media Device
193 // Path, then we have found a match.
194 //
195
196 Match = FALSE;
197
198 if (DevicePath != NULL) {
199
200 PreviousNodeIsHardDriveDevicePath = FALSE;
201
202 DevPath = DevicePath;
203
204 //
205 // Check for end of device path type
206 //
207
208 for (; ;) {
209
210 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
211 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
212
213 HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
214
215 if (PreviousNodeIsHardDriveDevicePath == FALSE) {
216
217 Next = NextDevicePathNode(DevPath);
218 if (IsDevicePathEndType(Next)) {
219 if ((HardDriveDevicePath->MBRType == MBRType) &&
220 (HardDriveDevicePath->SignatureType == SignatureType)) {
221 switch(SignatureType) {
222 case SIGNATURE_TYPE_MBR:
223 if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
224 Match = TRUE;
225 }
226 break;
227 case SIGNATURE_TYPE_GUID:
228 if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
229 Match = TRUE;
230 }
231 break;
232 }
233 }
234 }
235 }
236 PreviousNodeIsHardDriveDevicePath = TRUE;
237 } else {
238 PreviousNodeIsHardDriveDevicePath = FALSE;
239 }
240
241 if (IsDevicePathEnd(DevPath)) {
242 break;
243 }
244
245 DevPath = NextDevicePathNode(DevPath);
246 }
247
248 }
249
250 if (Match == FALSE) {
251 BlockIoBuffer[Index] = NULL;
252 } else {
253 *NoHandles = *NoHandles + 1;
254 }
255 }
256
257 //
258 // If there are no matches, then return
259 //
260
261 if (*NoHandles == 0) {
262 FreePool(BlockIoBuffer);
263 *NoHandles = 0;
264 *Buffer = NULL;
265 return EFI_SUCCESS;
266 }
267
268 //
269 // Allocate space for the return buffer of device handles.
270 //
271
272 *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
273
274 if (*Buffer == NULL) {
275 FreePool(BlockIoBuffer);
276 *NoHandles = 0;
277 *Buffer = NULL;
278 return EFI_OUT_OF_RESOURCES;
279 }
280
281 //
282 // Build list of matching device handles.
283 //
284
285 *NoHandles = 0;
286 for(Index=0;Index<NoBlockIoHandles;Index++) {
287 if (BlockIoBuffer[Index] != NULL) {
288 (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
289 *NoHandles = *NoHandles + 1;
290 }
291 }
292
293 FreePool(BlockIoBuffer);
294
295 return EFI_SUCCESS;
296 }
297
298 EFI_FILE_HANDLE
LibOpenRoot(IN EFI_HANDLE DeviceHandle)299 LibOpenRoot (
300 IN EFI_HANDLE DeviceHandle
301 )
302 {
303 EFI_STATUS Status;
304 EFI_FILE_IO_INTERFACE *Volume;
305 EFI_FILE_HANDLE File;
306
307
308 //
309 // File the file system interface to the device
310 //
311
312 Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
313
314 //
315 // Open the root directory of the volume
316 //
317
318 if (!EFI_ERROR(Status)) {
319 Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
320 }
321
322 //
323 // Done
324 //
325
326 return EFI_ERROR(Status) ? NULL : File;
327 }
328
329 EFI_FILE_INFO *
LibFileInfo(IN EFI_FILE_HANDLE FHand)330 LibFileInfo (
331 IN EFI_FILE_HANDLE FHand
332 )
333 {
334 EFI_STATUS Status;
335 EFI_FILE_INFO *Buffer;
336 UINTN BufferSize;
337
338 //
339 // Initialize for GrowBuffer loop
340 //
341
342 Status = EFI_SUCCESS;
343 Buffer = NULL;
344 BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
345
346 //
347 // Call the real function
348 //
349
350 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
351 Status = uefi_call_wrapper(
352 FHand->GetInfo,
353 4,
354 FHand,
355 &GenericFileInfo,
356 &BufferSize,
357 Buffer
358 );
359 }
360
361 return Buffer;
362 }
363
364
365 EFI_FILE_SYSTEM_INFO *
LibFileSystemInfo(IN EFI_FILE_HANDLE FHand)366 LibFileSystemInfo (
367 IN EFI_FILE_HANDLE FHand
368 )
369 {
370 EFI_STATUS Status;
371 EFI_FILE_SYSTEM_INFO *Buffer;
372 UINTN BufferSize;
373
374 //
375 // Initialize for GrowBuffer loop
376 //
377
378 Status = EFI_SUCCESS;
379 Buffer = NULL;
380 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
381
382 //
383 // Call the real function
384 //
385
386 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
387 Status = uefi_call_wrapper(
388 FHand->GetInfo,
389 4,
390 FHand,
391 &FileSystemInfo,
392 &BufferSize,
393 Buffer
394 );
395 }
396
397 return Buffer;
398 }
399
400 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
LibFileSystemVolumeLabelInfo(IN EFI_FILE_HANDLE FHand)401 LibFileSystemVolumeLabelInfo (
402 IN EFI_FILE_HANDLE FHand
403 )
404 {
405 EFI_STATUS Status;
406 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
407 UINTN BufferSize;
408
409 //
410 // Initialize for GrowBuffer loop
411 //
412
413 Status = EFI_SUCCESS;
414 Buffer = NULL;
415 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
416
417 //
418 // Call the real function
419 //
420
421 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
422 Status = uefi_call_wrapper(
423 FHand->GetInfo,
424 4,
425 FHand,
426 &FileSystemVolumeLabelInfo,
427 &BufferSize,
428 Buffer
429 );
430 }
431
432 return Buffer;
433 }
434
435
436
437 EFI_STATUS
LibInstallProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)438 LibInstallProtocolInterfaces (
439 IN OUT EFI_HANDLE *Handle,
440 ...
441 )
442 {
443 va_list args;
444 EFI_STATUS Status;
445 EFI_GUID *Protocol;
446 VOID *Interface;
447 EFI_TPL OldTpl;
448 UINTN Index;
449 EFI_HANDLE OldHandle;
450
451 //
452 // Syncronize with notifcations
453 //
454
455 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
456 OldHandle = *Handle;
457
458 //
459 // Install the protocol interfaces
460 //
461
462 Index = 0;
463 Status = EFI_SUCCESS;
464 va_start (args, Handle);
465
466 while (!EFI_ERROR(Status)) {
467
468 //
469 // If protocol is NULL, then it's the end of the list
470 //
471
472 Protocol = va_arg(args, EFI_GUID *);
473 if (!Protocol) {
474 break;
475 }
476
477 Interface = va_arg(args, VOID *);
478
479 //
480 // Install it
481 //
482
483 DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
484 Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
485 if (EFI_ERROR(Status)) {
486 break;
487 }
488
489 Index += 1;
490 }
491 va_end (args);
492
493 //
494 // If there was an error, remove all the interfaces that were
495 // installed without any errors
496 //
497
498 if (EFI_ERROR(Status)) {
499 va_start (args, Handle);
500 while (Index) {
501
502 Protocol = va_arg(args, EFI_GUID *);
503 Interface = va_arg(args, VOID *);
504 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
505
506 Index -= 1;
507 }
508
509 *Handle = OldHandle;
510 va_end (args);
511 }
512
513 //
514 // Done
515 //
516
517 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
518 return Status;
519 }
520
521
522 VOID
LibUninstallProtocolInterfaces(IN EFI_HANDLE Handle,...)523 LibUninstallProtocolInterfaces (
524 IN EFI_HANDLE Handle,
525 ...
526 )
527 {
528 va_list args;
529 EFI_STATUS Status;
530 EFI_GUID *Protocol;
531 VOID *Interface;
532
533
534 va_start (args, Handle);
535 for (; ;) {
536
537 //
538 // If protocol is NULL, then it's the end of the list
539 //
540
541 Protocol = va_arg(args, EFI_GUID *);
542 if (!Protocol) {
543 break;
544 }
545
546 Interface = va_arg(args, VOID *);
547
548 //
549 // Uninstall it
550 //
551
552 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
553 if (EFI_ERROR(Status)) {
554 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
555 }
556 }
557 va_end (args);
558 }
559
560
561 EFI_STATUS
LibReinstallProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)562 LibReinstallProtocolInterfaces (
563 IN OUT EFI_HANDLE *Handle,
564 ...
565 )
566 {
567 va_list args;
568 EFI_STATUS Status;
569 EFI_GUID *Protocol;
570 VOID *OldInterface, *NewInterface;
571 EFI_TPL OldTpl;
572 UINTN Index;
573
574 //
575 // Syncronize with notifcations
576 //
577
578 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
579
580 //
581 // Install the protocol interfaces
582 //
583
584 Index = 0;
585 Status = EFI_SUCCESS;
586 va_start (args, Handle);
587
588 while (!EFI_ERROR(Status)) {
589
590 //
591 // If protocol is NULL, then it's the end of the list
592 //
593
594 Protocol = va_arg(args, EFI_GUID *);
595 if (!Protocol) {
596 break;
597 }
598
599 OldInterface = va_arg(args, VOID *);
600 NewInterface = va_arg(args, VOID *);
601
602 //
603 // Reinstall it
604 //
605
606 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
607 if (EFI_ERROR(Status)) {
608 break;
609 }
610
611 Index += 1;
612 }
613 va_end (args);
614
615 //
616 // If there was an error, undo all the interfaces that were
617 // reinstalled without any errors
618 //
619
620 if (EFI_ERROR(Status)) {
621 va_start (args, Handle);
622 while (Index) {
623
624 Protocol = va_arg(args, EFI_GUID *);
625 OldInterface = va_arg(args, VOID *);
626 NewInterface = va_arg(args, VOID *);
627
628 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
629
630 Index -= 1;
631 }
632 va_end (args);
633 }
634
635 //
636 // Done
637 //
638
639 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
640 return Status;
641 }
642