1 /** @file 2 Emulator Thunk to abstract OS services from pure EFI code 3 4 Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR> 5 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR> 6 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include <Uefi.h> 18 #include <Library/BaseLib.h> 19 #include <Library/BaseMemoryLib.h> 20 #include <Library/DebugLib.h> 21 #include <Library/MemoryAllocationLib.h> 22 23 #include <Protocol/EmuIoThunk.h> 24 25 26 #define EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('E','m','u','T') 27 28 typedef struct { 29 UINTN Signature; 30 EMU_IO_THUNK_PROTOCOL Data; 31 BOOLEAN EmuBusDriver; 32 LIST_ENTRY Link; 33 } EMU_IO_THUNK_PROTOCOL_DATA; 34 35 LIST_ENTRY mThunkList = INITIALIZE_LIST_HEAD_VARIABLE (mThunkList); 36 37 38 EFI_STATUS 39 EFIAPI 40 AddThunkProtocol ( 41 IN EMU_IO_THUNK_PROTOCOL *ThunkIo, 42 IN CHAR16 *ConfigString, 43 IN BOOLEAN EmuBusDriver 44 ) 45 { 46 CHAR16 *StartString; 47 CHAR16 *SubString; 48 UINTN Instance; 49 EMU_IO_THUNK_PROTOCOL_DATA *Private; 50 51 if (ThunkIo == NULL) { 52 return EFI_INVALID_PARAMETER; 53 } 54 55 Instance = 0; 56 StartString = AllocatePool (StrSize (ConfigString)); 57 StrCpy (StartString, ConfigString); 58 while (*StartString != '\0') { 59 60 // 61 // Find the end of the sub string 62 // 63 SubString = StartString; 64 while (*SubString != '\0' && *SubString != '!') { 65 SubString++; 66 } 67 68 if (*SubString == '!') { 69 // 70 // Replace token with '\0' to make sub strings. If this is the end 71 // of the string SubString will already point to NULL. 72 // 73 *SubString = '\0'; 74 SubString++; 75 } 76 77 Private = AllocatePool (sizeof (EMU_IO_THUNK_PROTOCOL_DATA)); 78 if (Private == NULL) { 79 return EFI_OUT_OF_RESOURCES; 80 } 81 Private->Signature = EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE; 82 Private->EmuBusDriver = EmuBusDriver; 83 84 CopyMem (&Private->Data, ThunkIo, sizeof (EMU_IO_THUNK_PROTOCOL)); 85 Private->Data.Instance = Instance++; 86 Private->Data.ConfigString = StartString; 87 88 InsertTailList (&mThunkList, &Private->Link); 89 90 // 91 // Parse Next sub string. This will point to '\0' if we are at the end. 92 // 93 StartString = SubString; 94 } 95 96 return EFI_SUCCESS; 97 } 98 99 100 EFI_STATUS 101 EFIAPI 102 GetNextThunkProtocol ( 103 IN BOOLEAN EmuBusDriver, 104 OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL 105 ) 106 { 107 LIST_ENTRY *Link; 108 EMU_IO_THUNK_PROTOCOL_DATA *Private; 109 110 if (mThunkList.ForwardLink == &mThunkList) { 111 // Skip parsing an empty list 112 return EFI_NOT_FOUND; 113 } 114 115 for (Link = mThunkList.ForwardLink; Link != &mThunkList; Link = Link->ForwardLink) { 116 Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE); 117 if (EmuBusDriver & !Private->EmuBusDriver) { 118 continue; 119 } else if (*Instance == NULL) { 120 // Find 1st match in list 121 *Instance = &Private->Data; 122 return EFI_SUCCESS; 123 } else if (*Instance == &Private->Data) { 124 // Matched previous call so look for valid next entry 125 Link = Link->ForwardLink; 126 if (Link == &mThunkList) { 127 return EFI_NOT_FOUND; 128 } 129 Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE); 130 *Instance = &Private->Data; 131 return EFI_SUCCESS; 132 } 133 } 134 135 136 return EFI_NOT_FOUND; 137 } 138 139