Imported Upstream version 3.0
[platform/upstream/gnu-efi.git] / lib / hand.c
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
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
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
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       *Start, *Next, *DevPath;
121     HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
122     BOOLEAN               Match;
123     BOOLEAN               PreviousNodeIsHardDriveDevicePath;
124
125     //
126     // Initialize for GrowBuffer loop
127     //
128
129     BlockIoBuffer = NULL;
130     BufferSize = 50 * sizeof(EFI_HANDLE);
131
132     //
133     // Call the real function
134     //
135
136     while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
137
138         //
139         // Get list of device handles that support the BLOCK_IO Protocol.
140         //
141
142         Status = uefi_call_wrapper(
143                         BS->LocateHandle,
144                         5,
145                         ByProtocol,
146                         &BlockIoProtocol,
147                         NULL,
148                         &BufferSize,
149                         BlockIoBuffer
150                         );
151
152     }
153
154     NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
155     if (EFI_ERROR(Status)) {
156         NoBlockIoHandles = 0;
157     }
158
159     //
160     // If there was an error or there are no device handles that support 
161     // the BLOCK_IO Protocol, then return.
162     //
163
164     if (NoBlockIoHandles == 0) {
165         FreePool(BlockIoBuffer);
166         *NoHandles = 0;
167         *Buffer = NULL;
168         return Status;
169     }
170
171     //
172     // Loop through all the device handles that support the BLOCK_IO Protocol
173     //
174
175     *NoHandles = 0;
176
177     for(Index=0;Index<NoBlockIoHandles;Index++) {
178
179         Status = uefi_call_wrapper(
180                                      BS->HandleProtocol, 
181                                         3,
182                                      BlockIoBuffer[Index], 
183                                      &DevicePathProtocol, 
184                                      (VOID*)&DevicePath
185                                      );
186
187         //
188         // Search DevicePath for a Hard Drive Media Device Path node.
189         // If one is found, then see if it matches the signature that was
190         // passed in.  If it does match, and the next node is the End of the
191         // device path, and the previous node is not a Hard Drive Media Device
192         // Path, then we have found a match.
193         //
194
195         Match = FALSE;
196
197         if (DevicePath != NULL) {
198
199             PreviousNodeIsHardDriveDevicePath = FALSE;
200
201             DevPath = DevicePath;
202             Start = DevPath;
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
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 *
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     Buffer = NULL;
343     BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
344
345     //
346     // Call the real function
347     //
348
349     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
350         Status = uefi_call_wrapper(
351                     FHand->GetInfo,
352                         4,
353                     FHand,
354                     &GenericFileInfo,
355                     &BufferSize,
356                     Buffer
357                     );
358     }
359
360     return Buffer;
361 }
362
363     
364 EFI_FILE_SYSTEM_INFO *
365 LibFileSystemInfo (
366     IN EFI_FILE_HANDLE      FHand
367     )
368 {
369     EFI_STATUS              Status;
370     EFI_FILE_SYSTEM_INFO    *Buffer;
371     UINTN                   BufferSize;
372
373     //
374     // Initialize for GrowBuffer loop
375     //
376
377     Buffer = NULL;
378     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
379
380     //
381     // Call the real function
382     //
383
384     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
385         Status = uefi_call_wrapper(
386                     FHand->GetInfo,
387                         4,
388                     FHand,
389                     &FileSystemInfo,
390                     &BufferSize,
391                     Buffer
392                     );
393     }
394
395     return Buffer;
396 }
397
398 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
399 LibFileSystemVolumeLabelInfo (
400     IN EFI_FILE_HANDLE      FHand
401     )
402 {
403     EFI_STATUS                        Status;
404     EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
405     UINTN                             BufferSize;
406
407     //
408     // Initialize for GrowBuffer loop
409     //
410
411     Buffer = NULL;
412     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
413
414     //
415     // Call the real function
416     //
417
418     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
419         Status = uefi_call_wrapper(
420                     FHand->GetInfo,
421                         4,
422                     FHand,
423                     &FileSystemVolumeLabelInfo,
424                     &BufferSize,
425                     Buffer
426                     );
427     }
428
429     return Buffer;
430 }
431
432     
433
434 EFI_STATUS
435 LibInstallProtocolInterfaces (
436     IN OUT EFI_HANDLE           *Handle,
437     ...
438     )
439 {
440     va_list         args;
441     EFI_STATUS      Status;
442     EFI_GUID        *Protocol;
443     VOID            *Interface;
444     EFI_TPL         OldTpl;
445     UINTN           Index;
446     EFI_HANDLE      OldHandle;
447
448     //
449     // Syncronize with notifcations
450     // 
451
452     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
453     OldHandle = *Handle;
454
455     //
456     // Install the protocol interfaces
457     //
458
459     Index = 0;
460     Status = EFI_SUCCESS;
461     va_start (args, Handle);
462
463     while (!EFI_ERROR(Status)) {
464
465         //
466         // If protocol is NULL, then it's the end of the list
467         //
468
469         Protocol = va_arg(args, EFI_GUID *);
470         if (!Protocol) {
471             break;
472         }
473
474         Interface = va_arg(args, VOID *);
475
476         //
477         // Install it
478         //
479
480         DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
481         Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
482         if (EFI_ERROR(Status)) {
483             break;
484         }
485
486         Index += 1;
487     }
488
489     //
490     // If there was an error, remove all the interfaces that were
491     // installed without any errors
492     //
493
494     if (EFI_ERROR(Status)) {
495         va_start (args, Handle);
496         while (Index) {
497
498             Protocol = va_arg(args, EFI_GUID *);
499             Interface = va_arg(args, VOID *);
500             uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
501
502             Index -= 1;
503         }        
504
505         *Handle = OldHandle;
506     }
507
508     //
509     // Done
510     //
511
512     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
513     return Status;
514 }
515
516
517 VOID
518 LibUninstallProtocolInterfaces (
519     IN EFI_HANDLE           Handle,
520     ...
521     )
522 {
523     va_list         args;
524     EFI_STATUS      Status;
525     EFI_GUID        *Protocol;
526     VOID            *Interface;
527
528     
529     va_start (args, Handle);
530     for (; ;) {
531
532         //
533         // If protocol is NULL, then it's the end of the list
534         //
535
536         Protocol = va_arg(args, EFI_GUID *);
537         if (!Protocol) {
538             break;
539         }
540
541         Interface = va_arg(args, VOID *);
542
543         //
544         // Uninstall it
545         //
546
547         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
548         if (EFI_ERROR(Status)) {
549             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
550         }
551     }
552 }    
553
554
555 EFI_STATUS
556 LibReinstallProtocolInterfaces (
557     IN OUT EFI_HANDLE           *Handle,
558     ...
559     )
560 {
561     va_list         args;
562     EFI_STATUS      Status;
563     EFI_GUID        *Protocol;
564     VOID            *OldInterface, *NewInterface;
565     EFI_TPL         OldTpl;
566     UINTN           Index;
567
568     //
569     // Syncronize with notifcations
570     // 
571
572     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
573
574     //
575     // Install the protocol interfaces
576     //
577
578     Index = 0;
579     Status = EFI_SUCCESS;
580     va_start (args, Handle);
581
582     while (!EFI_ERROR(Status)) {
583
584         //
585         // If protocol is NULL, then it's the end of the list
586         //
587
588         Protocol = va_arg(args, EFI_GUID *);
589         if (!Protocol) {
590             break;
591         }
592
593         OldInterface = va_arg(args, VOID *);
594         NewInterface = va_arg(args, VOID *);
595
596         //
597         // Reinstall it
598         //
599
600         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
601         if (EFI_ERROR(Status)) {
602             break;
603         }
604
605         Index += 1;
606     }
607
608     //
609     // If there was an error, undo all the interfaces that were
610     // reinstalled without any errors
611     //
612
613     if (EFI_ERROR(Status)) {
614         va_start (args, Handle);
615         while (Index) {
616
617             Protocol = va_arg(args, EFI_GUID *);
618             OldInterface = va_arg(args, VOID *);
619             NewInterface = va_arg(args, VOID *);
620
621             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
622
623             Index -= 1;
624         }        
625     }
626
627     //
628     // Done
629     //
630
631     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
632     return Status;
633 }