--- /dev/null
+/** @file\r
+ Emulator Thunk to abstract OS services from pure EFI code\r
+\r
+ Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>\r
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <Protocol/EmuIoThunk.h>\r
+\r
+\r
+#define EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('E','m','u','T')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EMU_IO_THUNK_PROTOCOL Data;\r
+ BOOLEAN EmuBusDriver;\r
+ LIST_ENTRY Link;\r
+} EMU_IO_THUNK_PROTOCOL_DATA;\r
+\r
+LIST_ENTRY mThunkList = INITIALIZE_LIST_HEAD_VARIABLE (mThunkList);\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+AddThunkProtocol (\r
+ IN EMU_IO_THUNK_PROTOCOL *ThunkIo, \r
+ IN CHAR16 *ConfigString,\r
+ IN BOOLEAN EmuBusDriver\r
+ )\r
+{\r
+ CHAR16 *StartString;\r
+ CHAR16 *SubString;\r
+ UINTN Instance;\r
+ EMU_IO_THUNK_PROTOCOL_DATA *Private;\r
+ \r
+ if (ThunkIo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ Instance = 0;\r
+ StartString = AllocatePool (StrSize (ConfigString));\r
+ StrCpy (StartString, ConfigString);\r
+ while (*StartString != '\0') {\r
+\r
+ //\r
+ // Find the end of the sub string\r
+ //\r
+ SubString = StartString;\r
+ while (*SubString != '\0' && *SubString != '!') {\r
+ SubString++;\r
+ }\r
+\r
+ if (*SubString == '!') {\r
+ //\r
+ // Replace token with '\0' to make sub strings. If this is the end\r
+ // of the string SubString will already point to NULL.\r
+ //\r
+ *SubString = '\0';\r
+ SubString++;\r
+ }\r
+\r
+ Private = AllocatePool (sizeof (EMU_IO_THUNK_PROTOCOL_DATA));\r
+ if (Private == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Private->Signature = EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE;\r
+ Private->EmuBusDriver = EmuBusDriver;\r
+\r
+ CopyMem (&Private->Data, ThunkIo, sizeof (EMU_IO_THUNK_PROTOCOL)); \r
+ Private->Data.Instance = Instance++;\r
+ Private->Data.ConfigString = StartString;\r
+ \r
+ InsertTailList (&mThunkList, &Private->Link);\r
+\r
+ //\r
+ // Parse Next sub string. This will point to '\0' if we are at the end.\r
+ //\r
+ StartString = SubString;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextThunkProtocol (\r
+ IN BOOLEAN EmuBusDriver,\r
+ OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL\r
+ )\r
+{\r
+ LIST_ENTRY *Link; \r
+ EMU_IO_THUNK_PROTOCOL_DATA *Private; \r
+ \r
+ if (mThunkList.ForwardLink == &mThunkList) {\r
+ // Skip parsing an empty list\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ for (Link = mThunkList.ForwardLink; Link != &mThunkList; Link = Link->ForwardLink) {\r
+ Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE);\r
+ if (EmuBusDriver & !Private->EmuBusDriver) {\r
+ continue;\r
+ } else if (*Instance == NULL) {\r
+ // Find 1st match in list\r
+ *Instance = &Private->Data;\r
+ return EFI_SUCCESS;\r
+ } else if (*Instance == &Private->Data) {\r
+ // Matched previous call so look for valid next entry\r
+ Link = Link->ForwardLink;\r
+ if (Link == &mThunkList) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE);\r
+ *Instance = &Private->Data;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r