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