1/*++
2
3Copyright (c) 1998  Intel Corporation
4
5Module Name:
6
7    hand.c
8
9Abstract:
10
11
12
13
14Revision History
15
16--*/
17
18#include "lib.h"
19#include "efistdarg.h"                        // !!!
20
21
22EFI_STATUS
23LibLocateProtocol (
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
57EFI_STATUS
58LibLocateHandle (
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
104EFI_STATUS
105LibLocateHandleByDiskSignature (
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    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            Start = DevPath;
204
205            //
206            // Check for end of device path type
207            //
208
209            for (; ;) {
210
211                if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
212                    (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
213
214                    HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
215
216                    if (PreviousNodeIsHardDriveDevicePath == FALSE) {
217
218                        Next = NextDevicePathNode(DevPath);
219                        if (IsDevicePathEndType(Next)) {
220                            if ((HardDriveDevicePath->MBRType == MBRType) &&
221                                (HardDriveDevicePath->SignatureType == SignatureType)) {
222                                    switch(SignatureType) {
223                                        case SIGNATURE_TYPE_MBR:
224                                            if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
225                                                Match = TRUE;
226                                            }
227                                            break;
228                                        case SIGNATURE_TYPE_GUID:
229                                            if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
230                                                Match = TRUE;
231                                            }
232                                            break;
233                                    }
234                            }
235                        }
236                    }
237                    PreviousNodeIsHardDriveDevicePath = TRUE;
238                } else {
239                    PreviousNodeIsHardDriveDevicePath = FALSE;
240                }
241
242                if (IsDevicePathEnd(DevPath)) {
243                    break;
244                }
245
246                DevPath = NextDevicePathNode(DevPath);
247            }
248
249        }
250
251        if (Match == FALSE) {
252            BlockIoBuffer[Index] = NULL;
253        } else {
254            *NoHandles = *NoHandles + 1;
255        }
256    }
257
258    //
259    // If there are no matches, then return
260    //
261
262    if (*NoHandles == 0) {
263        FreePool(BlockIoBuffer);
264        *NoHandles = 0;
265        *Buffer = NULL;
266        return EFI_SUCCESS;
267    }
268
269    //
270    // Allocate space for the return buffer of device handles.
271    //
272
273    *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
274
275    if (*Buffer == NULL) {
276        FreePool(BlockIoBuffer);
277        *NoHandles = 0;
278        *Buffer = NULL;
279        return EFI_OUT_OF_RESOURCES;
280    }
281
282    //
283    // Build list of matching device handles.
284    //
285
286    *NoHandles = 0;
287    for(Index=0;Index<NoBlockIoHandles;Index++) {
288        if (BlockIoBuffer[Index] != NULL) {
289            (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
290            *NoHandles = *NoHandles + 1;
291        }
292    }
293
294    FreePool(BlockIoBuffer);
295
296    return EFI_SUCCESS;
297}
298
299EFI_FILE_HANDLE
300LibOpenRoot (
301    IN EFI_HANDLE               DeviceHandle
302    )
303{
304    EFI_STATUS                  Status;
305    EFI_FILE_IO_INTERFACE       *Volume;
306    EFI_FILE_HANDLE             File;
307
308
309    //
310    // File the file system interface to the device
311    //
312
313    Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
314
315    //
316    // Open the root directory of the volume
317    //
318
319    if (!EFI_ERROR(Status)) {
320        Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
321    }
322
323    //
324    // Done
325    //
326
327    return EFI_ERROR(Status) ? NULL : File;
328}
329
330EFI_FILE_INFO *
331LibFileInfo (
332    IN EFI_FILE_HANDLE      FHand
333    )
334{
335    EFI_STATUS              Status;
336    EFI_FILE_INFO           *Buffer;
337    UINTN                   BufferSize;
338
339    //
340    // Initialize for GrowBuffer loop
341    //
342
343    Status = EFI_SUCCESS;
344    Buffer = NULL;
345    BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
346
347    //
348    // Call the real function
349    //
350
351    while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
352        Status = uefi_call_wrapper(
353		    FHand->GetInfo,
354			4,
355                    FHand,
356                    &GenericFileInfo,
357                    &BufferSize,
358                    Buffer
359                    );
360    }
361
362    return Buffer;
363}
364
365
366EFI_FILE_SYSTEM_INFO *
367LibFileSystemInfo (
368    IN EFI_FILE_HANDLE      FHand
369    )
370{
371    EFI_STATUS              Status;
372    EFI_FILE_SYSTEM_INFO    *Buffer;
373    UINTN                   BufferSize;
374
375    //
376    // Initialize for GrowBuffer loop
377    //
378
379    Status = EFI_SUCCESS;
380    Buffer = NULL;
381    BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
382
383    //
384    // Call the real function
385    //
386
387    while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
388        Status = uefi_call_wrapper(
389		    FHand->GetInfo,
390			4,
391                    FHand,
392                    &FileSystemInfo,
393                    &BufferSize,
394                    Buffer
395                    );
396    }
397
398    return Buffer;
399}
400
401EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
402LibFileSystemVolumeLabelInfo (
403    IN EFI_FILE_HANDLE      FHand
404    )
405{
406    EFI_STATUS                        Status;
407    EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
408    UINTN                             BufferSize;
409
410    //
411    // Initialize for GrowBuffer loop
412    //
413
414    Status = EFI_SUCCESS;
415    Buffer = NULL;
416    BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
417
418    //
419    // Call the real function
420    //
421
422    while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
423        Status = uefi_call_wrapper(
424		    FHand->GetInfo,
425			4,
426                    FHand,
427                    &FileSystemVolumeLabelInfo,
428                    &BufferSize,
429                    Buffer
430                    );
431    }
432
433    return Buffer;
434}
435
436
437
438EFI_STATUS
439LibInstallProtocolInterfaces (
440    IN OUT EFI_HANDLE           *Handle,
441    ...
442    )
443{
444    va_list         args;
445    EFI_STATUS      Status;
446    EFI_GUID        *Protocol;
447    VOID            *Interface;
448    EFI_TPL         OldTpl;
449    UINTN           Index;
450    EFI_HANDLE      OldHandle;
451
452    //
453    // Syncronize with notifcations
454    //
455
456    OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
457    OldHandle = *Handle;
458
459    //
460    // Install the protocol interfaces
461    //
462
463    Index = 0;
464    Status = EFI_SUCCESS;
465    va_start (args, Handle);
466
467    while (!EFI_ERROR(Status)) {
468
469        //
470        // If protocol is NULL, then it's the end of the list
471        //
472
473        Protocol = va_arg(args, EFI_GUID *);
474        if (!Protocol) {
475            break;
476        }
477
478        Interface = va_arg(args, VOID *);
479
480        //
481        // Install it
482        //
483
484        DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
485        Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
486        if (EFI_ERROR(Status)) {
487            break;
488        }
489
490        Index += 1;
491    }
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    }
511
512    //
513    // Done
514    //
515
516    uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
517    return Status;
518}
519
520
521VOID
522LibUninstallProtocolInterfaces (
523    IN EFI_HANDLE           Handle,
524    ...
525    )
526{
527    va_list         args;
528    EFI_STATUS      Status;
529    EFI_GUID        *Protocol;
530    VOID            *Interface;
531
532
533    va_start (args, Handle);
534    for (; ;) {
535
536        //
537        // If protocol is NULL, then it's the end of the list
538        //
539
540        Protocol = va_arg(args, EFI_GUID *);
541        if (!Protocol) {
542            break;
543        }
544
545        Interface = va_arg(args, VOID *);
546
547        //
548        // Uninstall it
549        //
550
551        Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
552        if (EFI_ERROR(Status)) {
553            DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
554        }
555    }
556}
557
558
559EFI_STATUS
560LibReinstallProtocolInterfaces (
561    IN OUT EFI_HANDLE           *Handle,
562    ...
563    )
564{
565    va_list         args;
566    EFI_STATUS      Status;
567    EFI_GUID        *Protocol;
568    VOID            *OldInterface, *NewInterface;
569    EFI_TPL         OldTpl;
570    UINTN           Index;
571
572    //
573    // Syncronize with notifcations
574    //
575
576    OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
577
578    //
579    // Install the protocol interfaces
580    //
581
582    Index = 0;
583    Status = EFI_SUCCESS;
584    va_start (args, Handle);
585
586    while (!EFI_ERROR(Status)) {
587
588        //
589        // If protocol is NULL, then it's the end of the list
590        //
591
592        Protocol = va_arg(args, EFI_GUID *);
593        if (!Protocol) {
594            break;
595        }
596
597        OldInterface = va_arg(args, VOID *);
598        NewInterface = va_arg(args, VOID *);
599
600        //
601        // Reinstall it
602        //
603
604        Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
605        if (EFI_ERROR(Status)) {
606            break;
607        }
608
609        Index += 1;
610    }
611
612    //
613    // If there was an error, undo all the interfaces that were
614    // reinstalled without any errors
615    //
616
617    if (EFI_ERROR(Status)) {
618        va_start (args, Handle);
619        while (Index) {
620
621            Protocol = va_arg(args, EFI_GUID *);
622            OldInterface = va_arg(args, VOID *);
623            NewInterface = va_arg(args, VOID *);
624
625            uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
626
627            Index -= 1;
628        }
629    }
630
631    //
632    // Done
633    //
634
635    uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
636    return Status;
637}
638