xref: /DragonStub/lib/hand.c (revision 70402aa91d9831b7f2ccae9e76c4dd7aff7c386a)
1530d68baSNigel Croxon /*++
2530d68baSNigel Croxon 
3530d68baSNigel Croxon Copyright (c) 1998  Intel Corporation
4530d68baSNigel Croxon 
5530d68baSNigel Croxon Module Name:
6530d68baSNigel Croxon 
7530d68baSNigel Croxon     hand.c
8530d68baSNigel Croxon 
9530d68baSNigel Croxon Abstract:
10530d68baSNigel Croxon 
11530d68baSNigel Croxon 
12530d68baSNigel Croxon 
13530d68baSNigel Croxon 
14530d68baSNigel Croxon Revision History
15530d68baSNigel Croxon 
16530d68baSNigel Croxon --*/
17530d68baSNigel Croxon 
18530d68baSNigel Croxon #include "lib.h"
19530d68baSNigel Croxon #include "efistdarg.h"                        // !!!
20530d68baSNigel Croxon 
21530d68baSNigel Croxon 
22530d68baSNigel Croxon EFI_STATUS
23530d68baSNigel Croxon LibLocateProtocol (
24530d68baSNigel Croxon     IN  EFI_GUID    *ProtocolGuid,
25530d68baSNigel Croxon     OUT VOID        **Interface
26530d68baSNigel Croxon     )
27530d68baSNigel Croxon //
28530d68baSNigel Croxon // Find the first instance of this Protocol in the system and return it's interface
29530d68baSNigel Croxon //
30530d68baSNigel Croxon {
31530d68baSNigel Croxon     EFI_STATUS      Status;
32530d68baSNigel Croxon     UINTN           NumberHandles, Index;
33530d68baSNigel Croxon     EFI_HANDLE      *Handles;
34530d68baSNigel Croxon 
35530d68baSNigel Croxon 
36530d68baSNigel Croxon     *Interface = NULL;
37530d68baSNigel Croxon     Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles);
38530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
39530d68baSNigel Croxon         DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n"));
40530d68baSNigel Croxon         return Status;
41530d68baSNigel Croxon     }
42530d68baSNigel Croxon 
43530d68baSNigel Croxon     for (Index=0; Index < NumberHandles; Index++) {
44530d68baSNigel Croxon         Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface);
45530d68baSNigel Croxon         if (!EFI_ERROR(Status)) {
46530d68baSNigel Croxon             break;
47530d68baSNigel Croxon         }
48530d68baSNigel Croxon     }
49530d68baSNigel Croxon 
50530d68baSNigel Croxon     if (Handles) {
51530d68baSNigel Croxon         FreePool (Handles);
52530d68baSNigel Croxon     }
53530d68baSNigel Croxon 
54530d68baSNigel Croxon     return Status;
55530d68baSNigel Croxon }
56530d68baSNigel Croxon 
57530d68baSNigel Croxon EFI_STATUS
58530d68baSNigel Croxon LibLocateHandle (
59530d68baSNigel Croxon     IN EFI_LOCATE_SEARCH_TYPE       SearchType,
60530d68baSNigel Croxon     IN EFI_GUID                     *Protocol OPTIONAL,
61530d68baSNigel Croxon     IN VOID                         *SearchKey OPTIONAL,
62530d68baSNigel Croxon     IN OUT UINTN                    *NoHandles,
63530d68baSNigel Croxon     OUT EFI_HANDLE                  **Buffer
64530d68baSNigel Croxon     )
65530d68baSNigel Croxon 
66530d68baSNigel Croxon {
67530d68baSNigel Croxon     EFI_STATUS          Status;
68530d68baSNigel Croxon     UINTN               BufferSize;
69530d68baSNigel Croxon 
70530d68baSNigel Croxon     //
71530d68baSNigel Croxon     // Initialize for GrowBuffer loop
72530d68baSNigel Croxon     //
73530d68baSNigel Croxon 
74530d68baSNigel Croxon     Status = EFI_SUCCESS;
75530d68baSNigel Croxon     *Buffer = NULL;
76530d68baSNigel Croxon     BufferSize = 50 * sizeof(EFI_HANDLE);
77530d68baSNigel Croxon 
78530d68baSNigel Croxon     //
79530d68baSNigel Croxon     // Call the real function
80530d68baSNigel Croxon     //
81530d68baSNigel Croxon 
82530d68baSNigel Croxon     while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
83530d68baSNigel Croxon 
84530d68baSNigel Croxon         Status = uefi_call_wrapper(
85530d68baSNigel Croxon 			BS->LocateHandle,
86530d68baSNigel Croxon 			5,
87530d68baSNigel Croxon                         SearchType,
88530d68baSNigel Croxon                         Protocol,
89530d68baSNigel Croxon                         SearchKey,
90530d68baSNigel Croxon                         &BufferSize,
91530d68baSNigel Croxon                         *Buffer
92530d68baSNigel Croxon                         );
93530d68baSNigel Croxon 
94530d68baSNigel Croxon     }
95530d68baSNigel Croxon 
96530d68baSNigel Croxon     *NoHandles = BufferSize / sizeof (EFI_HANDLE);
97530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
98530d68baSNigel Croxon         *NoHandles = 0;
99530d68baSNigel Croxon     }
100530d68baSNigel Croxon 
101530d68baSNigel Croxon     return Status;
102530d68baSNigel Croxon }
103530d68baSNigel Croxon 
104530d68baSNigel Croxon EFI_STATUS
105530d68baSNigel Croxon LibLocateHandleByDiskSignature (
106530d68baSNigel Croxon     IN UINT8                        MBRType,
107530d68baSNigel Croxon     IN UINT8                        SignatureType,
108530d68baSNigel Croxon     IN VOID                         *Signature,
109530d68baSNigel Croxon     IN OUT UINTN                    *NoHandles,
110530d68baSNigel Croxon     OUT EFI_HANDLE                  **Buffer
111530d68baSNigel Croxon     )
112530d68baSNigel Croxon 
113530d68baSNigel Croxon {
114530d68baSNigel Croxon     EFI_STATUS            Status;
115530d68baSNigel Croxon     UINTN                 BufferSize;
116530d68baSNigel Croxon     UINTN                 NoBlockIoHandles;
117530d68baSNigel Croxon     EFI_HANDLE            *BlockIoBuffer;
118530d68baSNigel Croxon     EFI_DEVICE_PATH       *DevicePath;
119530d68baSNigel Croxon     UINTN                 Index;
1201ecae7d4SNigel Croxon     EFI_DEVICE_PATH       *Next, *DevPath;
121530d68baSNigel Croxon     HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
122530d68baSNigel Croxon     BOOLEAN               Match;
123530d68baSNigel Croxon     BOOLEAN               PreviousNodeIsHardDriveDevicePath;
124530d68baSNigel Croxon 
125530d68baSNigel Croxon     //
126530d68baSNigel Croxon     // Initialize for GrowBuffer loop
127530d68baSNigel Croxon     //
128530d68baSNigel Croxon 
129530d68baSNigel Croxon     Status = EFI_SUCCESS;
130530d68baSNigel Croxon     BlockIoBuffer = NULL;
131530d68baSNigel Croxon     BufferSize = 50 * sizeof(EFI_HANDLE);
132530d68baSNigel Croxon 
133530d68baSNigel Croxon     //
134530d68baSNigel Croxon     // Call the real function
135530d68baSNigel Croxon     //
136530d68baSNigel Croxon 
137530d68baSNigel Croxon     while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
138530d68baSNigel Croxon 
139530d68baSNigel Croxon         //
140530d68baSNigel Croxon         // Get list of device handles that support the BLOCK_IO Protocol.
141530d68baSNigel Croxon         //
142530d68baSNigel Croxon 
143530d68baSNigel Croxon         Status = uefi_call_wrapper(
144530d68baSNigel Croxon 			BS->LocateHandle,
145530d68baSNigel Croxon 			5,
146530d68baSNigel Croxon                         ByProtocol,
147530d68baSNigel Croxon                         &BlockIoProtocol,
148530d68baSNigel Croxon                         NULL,
149530d68baSNigel Croxon                         &BufferSize,
150530d68baSNigel Croxon                         BlockIoBuffer
151530d68baSNigel Croxon                         );
152530d68baSNigel Croxon 
153530d68baSNigel Croxon     }
154530d68baSNigel Croxon 
155530d68baSNigel Croxon     NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
156530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
157530d68baSNigel Croxon         NoBlockIoHandles = 0;
158530d68baSNigel Croxon     }
159530d68baSNigel Croxon 
160530d68baSNigel Croxon     //
161530d68baSNigel Croxon     // If there was an error or there are no device handles that support
162530d68baSNigel Croxon     // the BLOCK_IO Protocol, then return.
163530d68baSNigel Croxon     //
164530d68baSNigel Croxon 
165530d68baSNigel Croxon     if (NoBlockIoHandles == 0) {
166530d68baSNigel Croxon         FreePool(BlockIoBuffer);
167530d68baSNigel Croxon         *NoHandles = 0;
168530d68baSNigel Croxon         *Buffer = NULL;
169530d68baSNigel Croxon         return Status;
170530d68baSNigel Croxon     }
171530d68baSNigel Croxon 
172530d68baSNigel Croxon     //
173530d68baSNigel Croxon     // Loop through all the device handles that support the BLOCK_IO Protocol
174530d68baSNigel Croxon     //
175530d68baSNigel Croxon 
176530d68baSNigel Croxon     *NoHandles = 0;
177530d68baSNigel Croxon 
178530d68baSNigel Croxon     for(Index=0;Index<NoBlockIoHandles;Index++) {
179530d68baSNigel Croxon 
180530d68baSNigel Croxon         Status = uefi_call_wrapper(
181530d68baSNigel Croxon 				     BS->HandleProtocol,
182530d68baSNigel Croxon 					3,
183530d68baSNigel Croxon 				     BlockIoBuffer[Index],
184530d68baSNigel Croxon                                      &DevicePathProtocol,
185530d68baSNigel Croxon                                      (VOID*)&DevicePath
186530d68baSNigel Croxon                                      );
187530d68baSNigel Croxon 
188530d68baSNigel Croxon         //
189530d68baSNigel Croxon         // Search DevicePath for a Hard Drive Media Device Path node.
190530d68baSNigel Croxon         // If one is found, then see if it matches the signature that was
191530d68baSNigel Croxon         // passed in.  If it does match, and the next node is the End of the
192530d68baSNigel Croxon         // device path, and the previous node is not a Hard Drive Media Device
193530d68baSNigel Croxon         // Path, then we have found a match.
194530d68baSNigel Croxon         //
195530d68baSNigel Croxon 
196530d68baSNigel Croxon         Match = FALSE;
197530d68baSNigel Croxon 
198530d68baSNigel Croxon         if (DevicePath != NULL) {
199530d68baSNigel Croxon 
200530d68baSNigel Croxon             PreviousNodeIsHardDriveDevicePath = FALSE;
201530d68baSNigel Croxon 
202530d68baSNigel Croxon             DevPath = DevicePath;
203530d68baSNigel Croxon 
204530d68baSNigel Croxon             //
205530d68baSNigel Croxon             // Check for end of device path type
206530d68baSNigel Croxon             //
207530d68baSNigel Croxon 
208530d68baSNigel Croxon             for (; ;) {
209530d68baSNigel Croxon 
210530d68baSNigel Croxon                 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
211530d68baSNigel Croxon                     (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
212530d68baSNigel Croxon 
213530d68baSNigel Croxon                     HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
214530d68baSNigel Croxon 
215530d68baSNigel Croxon                     if (PreviousNodeIsHardDriveDevicePath == FALSE) {
216530d68baSNigel Croxon 
217530d68baSNigel Croxon                         Next = NextDevicePathNode(DevPath);
218530d68baSNigel Croxon                         if (IsDevicePathEndType(Next)) {
219530d68baSNigel Croxon                             if ((HardDriveDevicePath->MBRType == MBRType) &&
220530d68baSNigel Croxon                                 (HardDriveDevicePath->SignatureType == SignatureType)) {
221530d68baSNigel Croxon                                     switch(SignatureType) {
222530d68baSNigel Croxon                                         case SIGNATURE_TYPE_MBR:
223530d68baSNigel Croxon                                             if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
224530d68baSNigel Croxon                                                 Match = TRUE;
225530d68baSNigel Croxon                                             }
226530d68baSNigel Croxon                                             break;
227530d68baSNigel Croxon                                         case SIGNATURE_TYPE_GUID:
228530d68baSNigel Croxon                                             if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
229530d68baSNigel Croxon                                                 Match = TRUE;
230530d68baSNigel Croxon                                             }
231530d68baSNigel Croxon                                             break;
232530d68baSNigel Croxon                                     }
233530d68baSNigel Croxon                             }
234530d68baSNigel Croxon                         }
235530d68baSNigel Croxon                     }
236530d68baSNigel Croxon                     PreviousNodeIsHardDriveDevicePath = TRUE;
237530d68baSNigel Croxon                 } else {
238530d68baSNigel Croxon                     PreviousNodeIsHardDriveDevicePath = FALSE;
239530d68baSNigel Croxon                 }
240530d68baSNigel Croxon 
241530d68baSNigel Croxon                 if (IsDevicePathEnd(DevPath)) {
242530d68baSNigel Croxon                     break;
243530d68baSNigel Croxon                 }
244530d68baSNigel Croxon 
245530d68baSNigel Croxon                 DevPath = NextDevicePathNode(DevPath);
246530d68baSNigel Croxon             }
247530d68baSNigel Croxon 
248530d68baSNigel Croxon         }
249530d68baSNigel Croxon 
250530d68baSNigel Croxon         if (Match == FALSE) {
251530d68baSNigel Croxon             BlockIoBuffer[Index] = NULL;
252530d68baSNigel Croxon         } else {
253530d68baSNigel Croxon             *NoHandles = *NoHandles + 1;
254530d68baSNigel Croxon         }
255530d68baSNigel Croxon     }
256530d68baSNigel Croxon 
257530d68baSNigel Croxon     //
258530d68baSNigel Croxon     // If there are no matches, then return
259530d68baSNigel Croxon     //
260530d68baSNigel Croxon 
261530d68baSNigel Croxon     if (*NoHandles == 0) {
262530d68baSNigel Croxon         FreePool(BlockIoBuffer);
263530d68baSNigel Croxon         *NoHandles = 0;
264530d68baSNigel Croxon         *Buffer = NULL;
265530d68baSNigel Croxon         return EFI_SUCCESS;
266530d68baSNigel Croxon     }
267530d68baSNigel Croxon 
268530d68baSNigel Croxon     //
269530d68baSNigel Croxon     // Allocate space for the return buffer of device handles.
270530d68baSNigel Croxon     //
271530d68baSNigel Croxon 
272530d68baSNigel Croxon     *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
273530d68baSNigel Croxon 
274530d68baSNigel Croxon     if (*Buffer == NULL) {
275530d68baSNigel Croxon         FreePool(BlockIoBuffer);
276530d68baSNigel Croxon         *NoHandles = 0;
277530d68baSNigel Croxon         *Buffer = NULL;
278530d68baSNigel Croxon         return EFI_OUT_OF_RESOURCES;
279530d68baSNigel Croxon     }
280530d68baSNigel Croxon 
281530d68baSNigel Croxon     //
282530d68baSNigel Croxon     // Build list of matching device handles.
283530d68baSNigel Croxon     //
284530d68baSNigel Croxon 
285530d68baSNigel Croxon     *NoHandles = 0;
286530d68baSNigel Croxon     for(Index=0;Index<NoBlockIoHandles;Index++) {
287530d68baSNigel Croxon         if (BlockIoBuffer[Index] != NULL) {
288530d68baSNigel Croxon             (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
289530d68baSNigel Croxon             *NoHandles = *NoHandles + 1;
290530d68baSNigel Croxon         }
291530d68baSNigel Croxon     }
292530d68baSNigel Croxon 
293530d68baSNigel Croxon     FreePool(BlockIoBuffer);
294530d68baSNigel Croxon 
295530d68baSNigel Croxon     return EFI_SUCCESS;
296530d68baSNigel Croxon }
297530d68baSNigel Croxon 
298530d68baSNigel Croxon EFI_FILE_HANDLE
299530d68baSNigel Croxon LibOpenRoot (
300530d68baSNigel Croxon     IN EFI_HANDLE               DeviceHandle
301530d68baSNigel Croxon     )
302530d68baSNigel Croxon {
303530d68baSNigel Croxon     EFI_STATUS                  Status;
304530d68baSNigel Croxon     EFI_FILE_IO_INTERFACE       *Volume;
305530d68baSNigel Croxon     EFI_FILE_HANDLE             File;
306530d68baSNigel Croxon 
307530d68baSNigel Croxon 
308530d68baSNigel Croxon     //
309530d68baSNigel Croxon     // File the file system interface to the device
310530d68baSNigel Croxon     //
311530d68baSNigel Croxon 
312530d68baSNigel Croxon     Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
313530d68baSNigel Croxon 
314530d68baSNigel Croxon     //
315530d68baSNigel Croxon     // Open the root directory of the volume
316530d68baSNigel Croxon     //
317530d68baSNigel Croxon 
318530d68baSNigel Croxon     if (!EFI_ERROR(Status)) {
319530d68baSNigel Croxon         Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
320530d68baSNigel Croxon     }
321530d68baSNigel Croxon 
322530d68baSNigel Croxon     //
323530d68baSNigel Croxon     // Done
324530d68baSNigel Croxon     //
325530d68baSNigel Croxon 
326530d68baSNigel Croxon     return EFI_ERROR(Status) ? NULL : File;
327530d68baSNigel Croxon }
328530d68baSNigel Croxon 
329530d68baSNigel Croxon EFI_FILE_INFO *
330530d68baSNigel Croxon LibFileInfo (
331530d68baSNigel Croxon     IN EFI_FILE_HANDLE      FHand
332530d68baSNigel Croxon     )
333530d68baSNigel Croxon {
334530d68baSNigel Croxon     EFI_STATUS              Status;
335530d68baSNigel Croxon     EFI_FILE_INFO           *Buffer;
336530d68baSNigel Croxon     UINTN                   BufferSize;
337530d68baSNigel Croxon 
338530d68baSNigel Croxon     //
339530d68baSNigel Croxon     // Initialize for GrowBuffer loop
340530d68baSNigel Croxon     //
341530d68baSNigel Croxon 
342530d68baSNigel Croxon     Status = EFI_SUCCESS;
343530d68baSNigel Croxon     Buffer = NULL;
344530d68baSNigel Croxon     BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
345530d68baSNigel Croxon 
346530d68baSNigel Croxon     //
347530d68baSNigel Croxon     // Call the real function
348530d68baSNigel Croxon     //
349530d68baSNigel Croxon 
350530d68baSNigel Croxon     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
351530d68baSNigel Croxon         Status = uefi_call_wrapper(
352530d68baSNigel Croxon 		    FHand->GetInfo,
353530d68baSNigel Croxon 			4,
354530d68baSNigel Croxon                     FHand,
355530d68baSNigel Croxon                     &GenericFileInfo,
356530d68baSNigel Croxon                     &BufferSize,
357530d68baSNigel Croxon                     Buffer
358530d68baSNigel Croxon                     );
359530d68baSNigel Croxon     }
360530d68baSNigel Croxon 
361530d68baSNigel Croxon     return Buffer;
362530d68baSNigel Croxon }
363530d68baSNigel Croxon 
364530d68baSNigel Croxon 
365530d68baSNigel Croxon EFI_FILE_SYSTEM_INFO *
366530d68baSNigel Croxon LibFileSystemInfo (
367530d68baSNigel Croxon     IN EFI_FILE_HANDLE      FHand
368530d68baSNigel Croxon     )
369530d68baSNigel Croxon {
370530d68baSNigel Croxon     EFI_STATUS              Status;
371530d68baSNigel Croxon     EFI_FILE_SYSTEM_INFO    *Buffer;
372530d68baSNigel Croxon     UINTN                   BufferSize;
373530d68baSNigel Croxon 
374530d68baSNigel Croxon     //
375530d68baSNigel Croxon     // Initialize for GrowBuffer loop
376530d68baSNigel Croxon     //
377530d68baSNigel Croxon 
378530d68baSNigel Croxon     Status = EFI_SUCCESS;
379530d68baSNigel Croxon     Buffer = NULL;
380530d68baSNigel Croxon     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
381530d68baSNigel Croxon 
382530d68baSNigel Croxon     //
383530d68baSNigel Croxon     // Call the real function
384530d68baSNigel Croxon     //
385530d68baSNigel Croxon 
386530d68baSNigel Croxon     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
387530d68baSNigel Croxon         Status = uefi_call_wrapper(
388530d68baSNigel Croxon 		    FHand->GetInfo,
389530d68baSNigel Croxon 			4,
390530d68baSNigel Croxon                     FHand,
391530d68baSNigel Croxon                     &FileSystemInfo,
392530d68baSNigel Croxon                     &BufferSize,
393530d68baSNigel Croxon                     Buffer
394530d68baSNigel Croxon                     );
395530d68baSNigel Croxon     }
396530d68baSNigel Croxon 
397530d68baSNigel Croxon     return Buffer;
398530d68baSNigel Croxon }
399530d68baSNigel Croxon 
400530d68baSNigel Croxon EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
401530d68baSNigel Croxon LibFileSystemVolumeLabelInfo (
402530d68baSNigel Croxon     IN EFI_FILE_HANDLE      FHand
403530d68baSNigel Croxon     )
404530d68baSNigel Croxon {
405530d68baSNigel Croxon     EFI_STATUS                        Status;
406530d68baSNigel Croxon     EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
407530d68baSNigel Croxon     UINTN                             BufferSize;
408530d68baSNigel Croxon 
409530d68baSNigel Croxon     //
410530d68baSNigel Croxon     // Initialize for GrowBuffer loop
411530d68baSNigel Croxon     //
412530d68baSNigel Croxon 
413530d68baSNigel Croxon     Status = EFI_SUCCESS;
414530d68baSNigel Croxon     Buffer = NULL;
415530d68baSNigel Croxon     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
416530d68baSNigel Croxon 
417530d68baSNigel Croxon     //
418530d68baSNigel Croxon     // Call the real function
419530d68baSNigel Croxon     //
420530d68baSNigel Croxon 
421530d68baSNigel Croxon     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
422530d68baSNigel Croxon         Status = uefi_call_wrapper(
423530d68baSNigel Croxon 		    FHand->GetInfo,
424530d68baSNigel Croxon 			4,
425530d68baSNigel Croxon                     FHand,
426530d68baSNigel Croxon                     &FileSystemVolumeLabelInfo,
427530d68baSNigel Croxon                     &BufferSize,
428530d68baSNigel Croxon                     Buffer
429530d68baSNigel Croxon                     );
430530d68baSNigel Croxon     }
431530d68baSNigel Croxon 
432530d68baSNigel Croxon     return Buffer;
433530d68baSNigel Croxon }
434530d68baSNigel Croxon 
435530d68baSNigel Croxon 
436530d68baSNigel Croxon 
437530d68baSNigel Croxon EFI_STATUS
438530d68baSNigel Croxon LibInstallProtocolInterfaces (
439530d68baSNigel Croxon     IN OUT EFI_HANDLE           *Handle,
440530d68baSNigel Croxon     ...
441530d68baSNigel Croxon     )
442530d68baSNigel Croxon {
443530d68baSNigel Croxon     va_list         args;
444530d68baSNigel Croxon     EFI_STATUS      Status;
445530d68baSNigel Croxon     EFI_GUID        *Protocol;
446530d68baSNigel Croxon     VOID            *Interface;
447530d68baSNigel Croxon     EFI_TPL         OldTpl;
448530d68baSNigel Croxon     UINTN           Index;
449530d68baSNigel Croxon     EFI_HANDLE      OldHandle;
450530d68baSNigel Croxon 
451530d68baSNigel Croxon     //
452530d68baSNigel Croxon     // Syncronize with notifcations
453530d68baSNigel Croxon     //
454530d68baSNigel Croxon 
455530d68baSNigel Croxon     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
456530d68baSNigel Croxon     OldHandle = *Handle;
457530d68baSNigel Croxon 
458530d68baSNigel Croxon     //
459530d68baSNigel Croxon     // Install the protocol interfaces
460530d68baSNigel Croxon     //
461530d68baSNigel Croxon 
462530d68baSNigel Croxon     Index = 0;
463530d68baSNigel Croxon     Status = EFI_SUCCESS;
464530d68baSNigel Croxon     va_start (args, Handle);
465530d68baSNigel Croxon 
466530d68baSNigel Croxon     while (!EFI_ERROR(Status)) {
467530d68baSNigel Croxon 
468530d68baSNigel Croxon         //
469530d68baSNigel Croxon         // If protocol is NULL, then it's the end of the list
470530d68baSNigel Croxon         //
471530d68baSNigel Croxon 
472530d68baSNigel Croxon         Protocol = va_arg(args, EFI_GUID *);
473530d68baSNigel Croxon         if (!Protocol) {
474530d68baSNigel Croxon             break;
475530d68baSNigel Croxon         }
476530d68baSNigel Croxon 
477530d68baSNigel Croxon         Interface = va_arg(args, VOID *);
478530d68baSNigel Croxon 
479530d68baSNigel Croxon         //
480530d68baSNigel Croxon         // Install it
481530d68baSNigel Croxon         //
482530d68baSNigel Croxon 
483530d68baSNigel Croxon         DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
484530d68baSNigel Croxon         Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
485530d68baSNigel Croxon         if (EFI_ERROR(Status)) {
486530d68baSNigel Croxon             break;
487530d68baSNigel Croxon         }
488530d68baSNigel Croxon 
489530d68baSNigel Croxon         Index += 1;
490530d68baSNigel Croxon     }
4910ec661b3SHeinrich Schuchardt     va_end (args);
492530d68baSNigel Croxon 
493530d68baSNigel Croxon     //
494530d68baSNigel Croxon     // If there was an error, remove all the interfaces that were
495530d68baSNigel Croxon     // installed without any errors
496530d68baSNigel Croxon     //
497530d68baSNigel Croxon 
498530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
499530d68baSNigel Croxon         va_start (args, Handle);
500530d68baSNigel Croxon         while (Index) {
501530d68baSNigel Croxon 
502530d68baSNigel Croxon             Protocol = va_arg(args, EFI_GUID *);
503530d68baSNigel Croxon             Interface = va_arg(args, VOID *);
504530d68baSNigel Croxon             uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
505530d68baSNigel Croxon 
506530d68baSNigel Croxon             Index -= 1;
507530d68baSNigel Croxon         }
508530d68baSNigel Croxon 
509530d68baSNigel Croxon         *Handle = OldHandle;
5100ec661b3SHeinrich Schuchardt         va_end (args);
511530d68baSNigel Croxon     }
512530d68baSNigel Croxon 
513530d68baSNigel Croxon     //
514530d68baSNigel Croxon     // Done
515530d68baSNigel Croxon     //
516530d68baSNigel Croxon 
517530d68baSNigel Croxon     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
518530d68baSNigel Croxon     return Status;
519530d68baSNigel Croxon }
520530d68baSNigel Croxon 
521530d68baSNigel Croxon 
522530d68baSNigel Croxon VOID
523530d68baSNigel Croxon LibUninstallProtocolInterfaces (
524530d68baSNigel Croxon     IN EFI_HANDLE           Handle,
525530d68baSNigel Croxon     ...
526530d68baSNigel Croxon     )
527530d68baSNigel Croxon {
528530d68baSNigel Croxon     va_list         args;
529530d68baSNigel Croxon     EFI_STATUS      Status;
530530d68baSNigel Croxon     EFI_GUID        *Protocol;
531530d68baSNigel Croxon     VOID            *Interface;
532530d68baSNigel Croxon 
533530d68baSNigel Croxon 
534530d68baSNigel Croxon     va_start (args, Handle);
535530d68baSNigel Croxon     for (; ;) {
536530d68baSNigel Croxon 
537530d68baSNigel Croxon         //
538530d68baSNigel Croxon         // If protocol is NULL, then it's the end of the list
539530d68baSNigel Croxon         //
540530d68baSNigel Croxon 
541530d68baSNigel Croxon         Protocol = va_arg(args, EFI_GUID *);
542530d68baSNigel Croxon         if (!Protocol) {
543530d68baSNigel Croxon             break;
544530d68baSNigel Croxon         }
545530d68baSNigel Croxon 
546530d68baSNigel Croxon         Interface = va_arg(args, VOID *);
547530d68baSNigel Croxon 
548530d68baSNigel Croxon         //
549530d68baSNigel Croxon         // Uninstall it
550530d68baSNigel Croxon         //
551530d68baSNigel Croxon 
552530d68baSNigel Croxon         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
553530d68baSNigel Croxon         if (EFI_ERROR(Status)) {
554530d68baSNigel Croxon             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
555530d68baSNigel Croxon         }
556530d68baSNigel Croxon     }
5570ec661b3SHeinrich Schuchardt     va_end (args);
558530d68baSNigel Croxon }
559530d68baSNigel Croxon 
560530d68baSNigel Croxon 
561530d68baSNigel Croxon EFI_STATUS
562530d68baSNigel Croxon LibReinstallProtocolInterfaces (
563530d68baSNigel Croxon     IN OUT EFI_HANDLE           *Handle,
564530d68baSNigel Croxon     ...
565530d68baSNigel Croxon     )
566530d68baSNigel Croxon {
567530d68baSNigel Croxon     va_list         args;
568530d68baSNigel Croxon     EFI_STATUS      Status;
569530d68baSNigel Croxon     EFI_GUID        *Protocol;
570530d68baSNigel Croxon     VOID            *OldInterface, *NewInterface;
571530d68baSNigel Croxon     EFI_TPL         OldTpl;
572530d68baSNigel Croxon     UINTN           Index;
573530d68baSNigel Croxon 
574530d68baSNigel Croxon     //
575530d68baSNigel Croxon     // Syncronize with notifcations
576530d68baSNigel Croxon     //
577530d68baSNigel Croxon 
578530d68baSNigel Croxon     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
579530d68baSNigel Croxon 
580530d68baSNigel Croxon     //
581530d68baSNigel Croxon     // Install the protocol interfaces
582530d68baSNigel Croxon     //
583530d68baSNigel Croxon 
584530d68baSNigel Croxon     Index = 0;
585530d68baSNigel Croxon     Status = EFI_SUCCESS;
586530d68baSNigel Croxon     va_start (args, Handle);
587530d68baSNigel Croxon 
588530d68baSNigel Croxon     while (!EFI_ERROR(Status)) {
589530d68baSNigel Croxon 
590530d68baSNigel Croxon         //
591530d68baSNigel Croxon         // If protocol is NULL, then it's the end of the list
592530d68baSNigel Croxon         //
593530d68baSNigel Croxon 
594530d68baSNigel Croxon         Protocol = va_arg(args, EFI_GUID *);
595530d68baSNigel Croxon         if (!Protocol) {
596530d68baSNigel Croxon             break;
597530d68baSNigel Croxon         }
598530d68baSNigel Croxon 
599530d68baSNigel Croxon         OldInterface = va_arg(args, VOID *);
600530d68baSNigel Croxon         NewInterface = va_arg(args, VOID *);
601530d68baSNigel Croxon 
602530d68baSNigel Croxon         //
603530d68baSNigel Croxon         // Reinstall it
604530d68baSNigel Croxon         //
605530d68baSNigel Croxon 
606530d68baSNigel Croxon         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
607530d68baSNigel Croxon         if (EFI_ERROR(Status)) {
608530d68baSNigel Croxon             break;
609530d68baSNigel Croxon         }
610530d68baSNigel Croxon 
611530d68baSNigel Croxon         Index += 1;
612530d68baSNigel Croxon     }
613*70402aa9SHeinrich Schuchardt     va_end (args);
614530d68baSNigel Croxon 
615530d68baSNigel Croxon     //
616530d68baSNigel Croxon     // If there was an error, undo all the interfaces that were
617530d68baSNigel Croxon     // reinstalled without any errors
618530d68baSNigel Croxon     //
619530d68baSNigel Croxon 
620530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
621530d68baSNigel Croxon         va_start (args, Handle);
622530d68baSNigel Croxon         while (Index) {
623530d68baSNigel Croxon 
624530d68baSNigel Croxon             Protocol = va_arg(args, EFI_GUID *);
625530d68baSNigel Croxon             OldInterface = va_arg(args, VOID *);
626530d68baSNigel Croxon             NewInterface = va_arg(args, VOID *);
627530d68baSNigel Croxon 
628530d68baSNigel Croxon             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
629530d68baSNigel Croxon 
630530d68baSNigel Croxon             Index -= 1;
631530d68baSNigel Croxon         }
632*70402aa9SHeinrich Schuchardt         va_end (args);
633530d68baSNigel Croxon     }
634530d68baSNigel Croxon 
635530d68baSNigel Croxon     //
636530d68baSNigel Croxon     // Done
637530d68baSNigel Croxon     //
638530d68baSNigel Croxon 
639530d68baSNigel Croxon     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
640530d68baSNigel Croxon     return Status;
641530d68baSNigel Croxon }
642