Merge /u/esben/gnu-efi/ branch intptr-t-fix into master
[syslinux-gnu-efi.git] / lib / hand.c
blob6864765e0075735920f1f4b7e18c0628c2ebfb4d
1 /*++
3 Copyright (c) 1998 Intel Corporation
5 Module Name:
7 hand.c
9 Abstract:
14 Revision History
16 --*/
18 #include "lib.h"
19 #include "efistdarg.h" // !!!
22 EFI_STATUS
23 LibLocateProtocol (
24 IN EFI_GUID *ProtocolGuid,
25 OUT VOID **Interface
28 // Find the first instance of this Protocol in the system and return it's interface
31 EFI_STATUS Status;
32 UINTN NumberHandles, Index;
33 EFI_HANDLE *Handles;
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;
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;
50 if (Handles) {
51 FreePool (Handles);
54 return Status;
57 EFI_STATUS
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
67 EFI_STATUS Status;
68 UINTN BufferSize;
71 // Initialize for GrowBuffer loop
74 Status = EFI_SUCCESS;
75 *Buffer = NULL;
76 BufferSize = 50 * sizeof(EFI_HANDLE);
79 // Call the real function
82 while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
84 Status = uefi_call_wrapper(
85 BS->LocateHandle,
87 SearchType,
88 Protocol,
89 SearchKey,
90 &BufferSize,
91 *Buffer
96 *NoHandles = BufferSize / sizeof (EFI_HANDLE);
97 if (EFI_ERROR(Status)) {
98 *NoHandles = 0;
101 return Status;
104 EFI_STATUS
105 LibLocateHandleByDiskSignature (
106 IN UINT8 MBRType,
107 IN UINT8 SignatureType,
108 IN VOID *Signature,
109 IN OUT UINTN *NoHandles,
110 OUT EFI_HANDLE **Buffer
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;
126 // Initialize for GrowBuffer loop
129 Status = EFI_SUCCESS;
130 BlockIoBuffer = NULL;
131 BufferSize = 50 * sizeof(EFI_HANDLE);
134 // Call the real function
137 while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
140 // Get list of device handles that support the BLOCK_IO Protocol.
143 Status = uefi_call_wrapper(
144 BS->LocateHandle,
146 ByProtocol,
147 &BlockIoProtocol,
148 NULL,
149 &BufferSize,
150 BlockIoBuffer
155 NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
156 if (EFI_ERROR(Status)) {
157 NoBlockIoHandles = 0;
161 // If there was an error or there are no device handles that support
162 // the BLOCK_IO Protocol, then return.
165 if (NoBlockIoHandles == 0) {
166 FreePool(BlockIoBuffer);
167 *NoHandles = 0;
168 *Buffer = NULL;
169 return Status;
173 // Loop through all the device handles that support the BLOCK_IO Protocol
176 *NoHandles = 0;
178 for(Index=0;Index<NoBlockIoHandles;Index++) {
180 Status = uefi_call_wrapper(
181 BS->HandleProtocol,
183 BlockIoBuffer[Index],
184 &DevicePathProtocol,
185 (VOID*)&DevicePath
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.
196 Match = FALSE;
198 if (DevicePath != NULL) {
200 PreviousNodeIsHardDriveDevicePath = FALSE;
202 DevPath = DevicePath;
205 // Check for end of device path type
208 for (; ;) {
210 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
211 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
213 HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
215 if (PreviousNodeIsHardDriveDevicePath == FALSE) {
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;
226 break;
227 case SIGNATURE_TYPE_GUID:
228 if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
229 Match = TRUE;
231 break;
236 PreviousNodeIsHardDriveDevicePath = TRUE;
237 } else {
238 PreviousNodeIsHardDriveDevicePath = FALSE;
241 if (IsDevicePathEnd(DevPath)) {
242 break;
245 DevPath = NextDevicePathNode(DevPath);
250 if (Match == FALSE) {
251 BlockIoBuffer[Index] = NULL;
252 } else {
253 *NoHandles = *NoHandles + 1;
258 // If there are no matches, then return
261 if (*NoHandles == 0) {
262 FreePool(BlockIoBuffer);
263 *NoHandles = 0;
264 *Buffer = NULL;
265 return EFI_SUCCESS;
269 // Allocate space for the return buffer of device handles.
272 *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
274 if (*Buffer == NULL) {
275 FreePool(BlockIoBuffer);
276 *NoHandles = 0;
277 *Buffer = NULL;
278 return EFI_OUT_OF_RESOURCES;
282 // Build list of matching device handles.
285 *NoHandles = 0;
286 for(Index=0;Index<NoBlockIoHandles;Index++) {
287 if (BlockIoBuffer[Index] != NULL) {
288 (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
289 *NoHandles = *NoHandles + 1;
293 FreePool(BlockIoBuffer);
295 return EFI_SUCCESS;
298 EFI_FILE_HANDLE
299 LibOpenRoot (
300 IN EFI_HANDLE DeviceHandle
303 EFI_STATUS Status;
304 EFI_FILE_IO_INTERFACE *Volume;
305 EFI_FILE_HANDLE File;
309 // File the file system interface to the device
312 Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
315 // Open the root directory of the volume
318 if (!EFI_ERROR(Status)) {
319 Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
323 // Done
326 return EFI_ERROR(Status) ? NULL : File;
329 EFI_FILE_INFO *
330 LibFileInfo (
331 IN EFI_FILE_HANDLE FHand
334 EFI_STATUS Status;
335 EFI_FILE_INFO *Buffer;
336 UINTN BufferSize;
339 // Initialize for GrowBuffer loop
342 Status = EFI_SUCCESS;
343 Buffer = NULL;
344 BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
347 // Call the real function
350 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
351 Status = uefi_call_wrapper(
352 FHand->GetInfo,
354 FHand,
355 &GenericFileInfo,
356 &BufferSize,
357 Buffer
361 return Buffer;
365 EFI_FILE_SYSTEM_INFO *
366 LibFileSystemInfo (
367 IN EFI_FILE_HANDLE FHand
370 EFI_STATUS Status;
371 EFI_FILE_SYSTEM_INFO *Buffer;
372 UINTN BufferSize;
375 // Initialize for GrowBuffer loop
378 Status = EFI_SUCCESS;
379 Buffer = NULL;
380 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
383 // Call the real function
386 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
387 Status = uefi_call_wrapper(
388 FHand->GetInfo,
390 FHand,
391 &FileSystemInfo,
392 &BufferSize,
393 Buffer
397 return Buffer;
400 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
401 LibFileSystemVolumeLabelInfo (
402 IN EFI_FILE_HANDLE FHand
405 EFI_STATUS Status;
406 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
407 UINTN BufferSize;
410 // Initialize for GrowBuffer loop
413 Status = EFI_SUCCESS;
414 Buffer = NULL;
415 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
418 // Call the real function
421 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
422 Status = uefi_call_wrapper(
423 FHand->GetInfo,
425 FHand,
426 &FileSystemVolumeLabelInfo,
427 &BufferSize,
428 Buffer
432 return Buffer;
437 EFI_STATUS
438 LibInstallProtocolInterfaces (
439 IN OUT EFI_HANDLE *Handle,
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;
452 // Syncronize with notifcations
455 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
456 OldHandle = *Handle;
459 // Install the protocol interfaces
462 Index = 0;
463 Status = EFI_SUCCESS;
464 va_start (args, Handle);
466 while (!EFI_ERROR(Status)) {
469 // If protocol is NULL, then it's the end of the list
472 Protocol = va_arg(args, EFI_GUID *);
473 if (!Protocol) {
474 break;
477 Interface = va_arg(args, VOID *);
480 // Install it
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;
489 Index += 1;
493 // If there was an error, remove all the interfaces that were
494 // installed without any errors
497 if (EFI_ERROR(Status)) {
498 va_start (args, Handle);
499 while (Index) {
501 Protocol = va_arg(args, EFI_GUID *);
502 Interface = va_arg(args, VOID *);
503 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
505 Index -= 1;
508 *Handle = OldHandle;
512 // Done
515 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
516 return Status;
520 VOID
521 LibUninstallProtocolInterfaces (
522 IN EFI_HANDLE Handle,
526 va_list args;
527 EFI_STATUS Status;
528 EFI_GUID *Protocol;
529 VOID *Interface;
532 va_start (args, Handle);
533 for (; ;) {
536 // If protocol is NULL, then it's the end of the list
539 Protocol = va_arg(args, EFI_GUID *);
540 if (!Protocol) {
541 break;
544 Interface = va_arg(args, VOID *);
547 // Uninstall it
550 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
551 if (EFI_ERROR(Status)) {
552 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
558 EFI_STATUS
559 LibReinstallProtocolInterfaces (
560 IN OUT EFI_HANDLE *Handle,
564 va_list args;
565 EFI_STATUS Status;
566 EFI_GUID *Protocol;
567 VOID *OldInterface, *NewInterface;
568 EFI_TPL OldTpl;
569 UINTN Index;
572 // Syncronize with notifcations
575 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
578 // Install the protocol interfaces
581 Index = 0;
582 Status = EFI_SUCCESS;
583 va_start (args, Handle);
585 while (!EFI_ERROR(Status)) {
588 // If protocol is NULL, then it's the end of the list
591 Protocol = va_arg(args, EFI_GUID *);
592 if (!Protocol) {
593 break;
596 OldInterface = va_arg(args, VOID *);
597 NewInterface = va_arg(args, VOID *);
600 // Reinstall it
603 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
604 if (EFI_ERROR(Status)) {
605 break;
608 Index += 1;
612 // If there was an error, undo all the interfaces that were
613 // reinstalled without any errors
616 if (EFI_ERROR(Status)) {
617 va_start (args, Handle);
618 while (Index) {
620 Protocol = va_arg(args, EFI_GUID *);
621 OldInterface = va_arg(args, VOID *);
622 NewInterface = va_arg(args, VOID *);
624 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
626 Index -= 1;
631 // Done
634 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
635 return Status;