summaryrefslogtreecommitdiff
path: root/Core/CORE_DXE/UefiHii/HiAccessConfig.c
blob: d165a1e54d93c90cd7cbff8db38e9fb4a173dccd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
//**********************************************************************
//**********************************************************************
//**                                                                  **
//**        (C)Copyright 1985-2007, American Megatrends, Inc.         **
//**                                                                  **
//**                       All Rights Reserved.                       **
//**                                                                  **
//**             6145-F Northbelt Pkwy, Norcross, GA 30071            **
//**                                                                  **
//**                       Phone: (770)-246-8600                      **
//**                                                                  **
//**********************************************************************
//**********************************************************************

//**********************************************************************
// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiAccessConfig.c 7     5/04/11 12:08p Artems $
//
// $Revision: 7 $
//
// $Date: 5/04/11 12:08p $
//**********************************************************************
// Revision History
// ----------------
// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiAccessConfig.c $
// 
// 7     5/04/11 12:08p Artems
// Bug fix: when variable is absent attribute state was undefined
// 
// 6     1/25/11 4:03p Artems
// EIP 51298: Fixed corruption in buffer size after passing it to
// ConfigToBlock function
// Added check for correct syntax of request string in ExtractConfig
// function
// 
// 5     9/30/10 6:12p Artems
// Removed unnecessary service functions
// 
// 3     2/19/10 4:01p Felixp
// Debug messages are removed.
// 
// 2     11/25/09 11:25a Felixp
// Action parameter of the Callback function is updated  based on UEFI
// errata
// 
// 1     10/09/09 6:12p Felixp
// 
// 1     3/18/07 5:23p Felixp
// 
//**********************************************************************
//<AMI_FHDR_START>
//
// Name:	HiiAccessConfig.c
//
// Description:	Hii Config Access protocol implementation
//
//<AMI_FHDR_END>
//**********************************************************************

#pragma warning (disable : 4090)

#include <AmiDxeLib.h>
#include <Protocol/HiiConfigAccess.h>
#include <Protocol/HiiConfigRouting.h>

#include "HiiPrivate.h"

extern const NAME_PATTERN GuidPattern;
extern const NAME_PATTERN NamePattern;
extern const NAME_PATTERN PathPattern;
extern const NAME_PATTERN AltCfgPattern;
extern const NAME_PATTERN OffsetPattern;
extern const NAME_PATTERN WidthPattern;
extern const NAME_PATTERN ValuePattern;
extern const CHAR16 HexDigit[];

UINTN EfiStrLen  (IN CHAR16 *String);
UINTN EfiStrSize (IN CHAR16 *String);
VOID  EfiStrCat  (IN CHAR16 *Destination, IN CHAR16 *Source);

//**************************** Protocol functions implementation ***************************


EFI_STATUS HiiAccessExtractConfig(
    IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
    IN CONST EFI_STRING Request,
    OUT EFI_STRING *Progress,
    OUT EFI_STRING *Results
)
{
    EFI_STATUS  Status;
    UINTN       Length;
    EFI_GUID    Guid;
    CHAR16      Name[80];
    CHAR16      *Pointer = Request;
    UINT8       *Var = NULL;
    EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
    CHAR16      *ErrorMarker;

    if(Request == NULL) {
        *Progress = NULL;
        return EFI_INVALID_PARAMETER;
    }

    Status = pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &ConfigRouting);
    if(EFI_ERROR(Status))
        return Status;

//check syntax for guid
    if(!CheckPattern(Request, &GuidPattern)) {
        *Progress = Request;
        return EFI_INVALID_PARAMETER;
    }
//extract guid
    ErrorMarker = Pointer;
    Pointer += 5;       //skip "GUID=" pattern
    Length = 32;        //length of guid in symbols
    StringToBlock(Pointer, Length, (UINT8 *)&Guid);
    Pointer += Length;
    if(*Pointer != L'&') {
        TRACE((TRACE_DXE_CORE, "HII Extract Config: Guid extraction failed\n"));
        *Progress = ErrorMarker;
        return EFI_INVALID_PARAMETER;
    }

//check syntax for name
    if(!CheckPattern(Pointer + 1, &NamePattern)) {
        *Progress = Pointer;
        return EFI_INVALID_PARAMETER;
    }
//extract name
    ErrorMarker = Pointer;
    Pointer += 6;       //skip '&NAME=' pattern
    Length = 80;
    StringToChar16(Pointer, &Length, Name);
    Pointer += (Length * 4);
    if(*Pointer != L'&') {
        TRACE((TRACE_DXE_CORE, "HII Extract Config: Name extraction failed\n"));
        *Progress = ErrorMarker;
        return EFI_INVALID_PARAMETER;
    }

//get variable by name and guid from nvram

    Length = 0;
    Status = GetEfiVariable(Name, &Guid, NULL, &Length, &Var);
    if(EFI_ERROR(Status)) {
        *Progress = Request;
        return Status;
    }

//find start of OFFSET/WIDTH/VALUE block
    Pointer++;      //skip '&'
    while((*Pointer != L'&') && (*Pointer != 0))    //skip PATH
            Pointer++;

    if(*Pointer == 0) {                     //OFFSET/WIDTH blocks are missed
        UINTN TempSize; 
        CHAR16 *TempString;
        CHAR16 *TempString2;

        TempSize = (EfiStrLen(L"&OFFSET=0&WIDTH=") + sizeof(Length) + 1) * sizeof(CHAR16);
        TempString = MallocZ(TempSize);
        if(TempString == NULL)
            return EFI_OUT_OF_RESOURCES;

        Swprintf_s(TempString, TempSize, L"&OFFSET=0&WIDTH=%x", Length);

        TempSize += EfiStrSize(Request);
        TempString2 = MallocZ(TempSize);
        if(TempString2 == NULL)
            return EFI_OUT_OF_RESOURCES;

        EfiStrCat(TempString2, Request);
        EfiStrCat(TempString2, TempString);

        Status = ConfigRouting->BlockToConfig(ConfigRouting, TempString2, Var, Length, Results, Progress);
        *Progress = Request + EfiStrLen(Request); //set Progress to end of ConfigHdr
        pBS->FreePool(TempString);
        pBS->FreePool(TempString2);
    } else {                                        //OFFSET/WIDTH block found, let's check if it's correct
        if(!CheckPattern(Pointer + 1, &OffsetPattern)) {
            *Progress = Pointer;
            return EFI_INVALID_PARAMETER;
        }
        Status = ConfigRouting->BlockToConfig(ConfigRouting, Request, Var, Length, Results, Progress);
    }
        
    pBS->FreePool(Var);

    return Status;
}

EFI_STATUS HiiAccessRouteConfig(
    IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
    IN CONST EFI_STRING Configuration,
    OUT EFI_STRING *Progress
)
{
    EFI_STATUS  Status;
    UINTN       Length;
    UINTN       VarSize;
    EFI_GUID    Guid;
    CHAR16      Name[80];
    CHAR16      *Pointer = Configuration;
    UINT8       *Var = NULL;
    EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
    EFI_HANDLE  Handle;
    UINT32      Attributes;

    if(Configuration == NULL)
    {
        *Progress = NULL;
        return EFI_INVALID_PARAMETER;
    }

    Status = pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &ConfigRouting);
    if(EFI_ERROR(Status))
        return Status;

//check syntax for guid
    if(!CheckPattern(Configuration, &GuidPattern))
    {
        *Progress = Configuration;
        return EFI_INVALID_PARAMETER;
    }

//check proper device path
        Status = FindDeviceHandle(Configuration, &Handle);
        if(EFI_ERROR(Status))
            return EFI_NOT_FOUND;

//extract guid
    Pointer += 5;       //skip "GUID=" pattern
    Length = 32;        //length of guid in bytes
    StringToBlock(Pointer, Length, (UINT8 *)&Guid);
    Pointer += Length;
    if(*Pointer != L'&')
    {
        TRACE((TRACE_DXE_CORE, "HII Route Config: Guid extraction failed\n"));
        *Progress = Pointer;
        return EFI_INVALID_PARAMETER;
    }

//check syntax for name
    if(!CheckPattern(Pointer + 1, &NamePattern))
    {
        *Progress = Pointer;
        return EFI_INVALID_PARAMETER;
    }
//extract name
    Pointer += 6;       //skip '&NAME=' pattern
    Length = 80;
    StringToChar16(Pointer, &Length, Name);
    Pointer += (Length * 4);
    if(*Pointer != L'&')
    {
        TRACE((TRACE_DXE_CORE, "HII Route Config: Name extraction failed\n"));
        *Progress = Pointer;
        return EFI_INVALID_PARAMETER;
    }

//get variable by name and guid from nvram

    Length = 0;
    Status = GetEfiVariable(Name, &Guid, &Attributes, &Length, &Var);
    if(EFI_ERROR(Status))   //requested variable not found
    {
        Var = NULL;
        Length = 0;
        Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
    }
    VarSize = Length;

    Status = ConfigRouting->ConfigToBlock(ConfigRouting, Configuration, Var, &Length, Progress);
    while(Status == EFI_DEVICE_ERROR) //block not large enough
    {
        if(Var != NULL)
            pBS->FreePool(Var);

        Status = pBS->AllocatePool(EfiBootServicesData, Length, &Var);
        if(EFI_ERROR(Status))
            return Status;

        VarSize = Length;
        Status = ConfigRouting->ConfigToBlock(ConfigRouting, Configuration, Var, &Length, Progress);
    }

    if(EFI_ERROR(Status))
        return Status;

    pRS->SetVariable(Name, &Guid, Attributes, VarSize, Var);

    pBS->FreePool(Var);

    return EFI_SUCCESS;
}

EFI_STATUS HiiAccessFormCallback(
    IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
    IN EFI_BROWSER_ACTION Action,
    IN EFI_QUESTION_ID QuestionId,
    IN UINT8 Type,
    IN EFI_IFR_TYPE_VALUE *Value,
    OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
)
{
    return EFI_UNSUPPORTED;
}

//**********************************************************************
//**********************************************************************
//**                                                                  **
//**        (C)Copyright 1985-2007, American Megatrends, Inc.         **
//**                                                                  **
//**                       All Rights Reserved.                       **
//**                                                                  **
//**             6145-F Northbelt Pkwy, Norcross, GA 30071            **
//**                                                                  **
//**                       Phone: (770)-246-8600                      **
//**                                                                  **
//**********************************************************************
//**********************************************************************