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
AddThunkProtocol(IN EMU_IO_THUNK_PROTOCOL * ThunkIo,IN CHAR16 * ConfigString,IN BOOLEAN EmuBusDriver)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
GetNextThunkProtocol(IN BOOLEAN EmuBusDriver,OUT EMU_IO_THUNK_PROTOCOL ** Instance OPTIONAL)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