/** @file Emulator Thunk to abstract OS services from pure EFI code Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #define EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('E','m','u','T') typedef struct { UINTN Signature; EMU_IO_THUNK_PROTOCOL Data; BOOLEAN EmuBusDriver; LIST_ENTRY Link; } EMU_IO_THUNK_PROTOCOL_DATA; LIST_ENTRY mThunkList = INITIALIZE_LIST_HEAD_VARIABLE (mThunkList); EFI_STATUS EFIAPI AddThunkProtocol ( IN EMU_IO_THUNK_PROTOCOL *ThunkIo, IN CHAR16 *ConfigString, IN BOOLEAN EmuBusDriver ) { UINTN Size; CHAR16 *StartString; CHAR16 *SubString; UINTN Instance; EMU_IO_THUNK_PROTOCOL_DATA *Private; if (ThunkIo == NULL) { return EFI_INVALID_PARAMETER; } Instance = 0; Size = StrSize (ConfigString); StartString = AllocatePool (Size); if (StartString == NULL) { return EFI_OUT_OF_RESOURCES; } StrCpyS (StartString, Size / sizeof (CHAR16), ConfigString); while (*StartString != '\0') { // // Find the end of the sub string // SubString = StartString; while (*SubString != '\0' && *SubString != '!') { SubString++; } if (*SubString == '!') { // // Replace token with '\0' to make sub strings. If this is the end // of the string SubString will already point to NULL. // *SubString = '\0'; SubString++; } Private = AllocatePool (sizeof (EMU_IO_THUNK_PROTOCOL_DATA)); if (Private == NULL) { return EFI_OUT_OF_RESOURCES; } Private->Signature = EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE; Private->EmuBusDriver = EmuBusDriver; CopyMem (&Private->Data, ThunkIo, sizeof (EMU_IO_THUNK_PROTOCOL)); Private->Data.Instance = (UINT16)Instance++; Private->Data.ConfigString = StartString; InsertTailList (&mThunkList, &Private->Link); // // Parse Next sub string. This will point to '\0' if we are at the end. // StartString = SubString; } return EFI_SUCCESS; } EFI_STATUS EFIAPI GetNextThunkProtocol ( IN BOOLEAN EmuBusDriver, OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL ) { LIST_ENTRY *Link; EMU_IO_THUNK_PROTOCOL_DATA *Private; if (mThunkList.ForwardLink == &mThunkList) { // Skip parsing an empty list return EFI_NOT_FOUND; } for (Link = mThunkList.ForwardLink; Link != &mThunkList; Link = Link->ForwardLink) { Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE); if (EmuBusDriver & !Private->EmuBusDriver) { continue; } else if (*Instance == NULL) { // Find 1st match in list *Instance = &Private->Data; return EFI_SUCCESS; } else if (*Instance == &Private->Data) { // Matched previous call so look for valid next entry Link = Link->ForwardLink; if (Link == &mThunkList) { return EFI_NOT_FOUND; } Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE); *Instance = &Private->Data; return EFI_SUCCESS; } } return EFI_NOT_FOUND; }