misc.c revision 1.1.1.1 1 1.1 jakllsch /* $NetBSD: misc.c,v 1.1.1.1 2014/04/01 16:16:06 jakllsch Exp $ */
2 1.1 jakllsch
3 1.1 jakllsch /*++
4 1.1 jakllsch
5 1.1 jakllsch Copyright (c) 1998 Intel Corporation
6 1.1 jakllsch
7 1.1 jakllsch Module Name:
8 1.1 jakllsch
9 1.1 jakllsch misc.c
10 1.1 jakllsch
11 1.1 jakllsch Abstract:
12 1.1 jakllsch
13 1.1 jakllsch
14 1.1 jakllsch
15 1.1 jakllsch
16 1.1 jakllsch Revision History
17 1.1 jakllsch
18 1.1 jakllsch --*/
19 1.1 jakllsch
20 1.1 jakllsch #include "lib.h"
21 1.1 jakllsch
22 1.1 jakllsch
23 1.1 jakllsch //
24 1.1 jakllsch //
25 1.1 jakllsch //
26 1.1 jakllsch
27 1.1 jakllsch VOID *
28 1.1 jakllsch AllocatePool (
29 1.1 jakllsch IN UINTN Size
30 1.1 jakllsch )
31 1.1 jakllsch {
32 1.1 jakllsch EFI_STATUS Status;
33 1.1 jakllsch VOID *p;
34 1.1 jakllsch
35 1.1 jakllsch Status = uefi_call_wrapper(BS->AllocatePool, 3, PoolAllocationType, Size, &p);
36 1.1 jakllsch if (EFI_ERROR(Status)) {
37 1.1 jakllsch DEBUG((D_ERROR, "AllocatePool: out of pool %x\n", Status));
38 1.1 jakllsch p = NULL;
39 1.1 jakllsch }
40 1.1 jakllsch return p;
41 1.1 jakllsch }
42 1.1 jakllsch
43 1.1 jakllsch VOID *
44 1.1 jakllsch AllocateZeroPool (
45 1.1 jakllsch IN UINTN Size
46 1.1 jakllsch )
47 1.1 jakllsch {
48 1.1 jakllsch VOID *p;
49 1.1 jakllsch
50 1.1 jakllsch p = AllocatePool (Size);
51 1.1 jakllsch if (p) {
52 1.1 jakllsch ZeroMem (p, Size);
53 1.1 jakllsch }
54 1.1 jakllsch
55 1.1 jakllsch return p;
56 1.1 jakllsch }
57 1.1 jakllsch
58 1.1 jakllsch VOID *
59 1.1 jakllsch ReallocatePool (
60 1.1 jakllsch IN VOID *OldPool,
61 1.1 jakllsch IN UINTN OldSize,
62 1.1 jakllsch IN UINTN NewSize
63 1.1 jakllsch )
64 1.1 jakllsch {
65 1.1 jakllsch VOID *NewPool;
66 1.1 jakllsch
67 1.1 jakllsch NewPool = NULL;
68 1.1 jakllsch if (NewSize) {
69 1.1 jakllsch NewPool = AllocatePool (NewSize);
70 1.1 jakllsch }
71 1.1 jakllsch
72 1.1 jakllsch if (OldPool) {
73 1.1 jakllsch if (NewPool) {
74 1.1 jakllsch CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
75 1.1 jakllsch }
76 1.1 jakllsch
77 1.1 jakllsch FreePool (OldPool);
78 1.1 jakllsch }
79 1.1 jakllsch
80 1.1 jakllsch return NewPool;
81 1.1 jakllsch }
82 1.1 jakllsch
83 1.1 jakllsch
84 1.1 jakllsch VOID
85 1.1 jakllsch FreePool (
86 1.1 jakllsch IN VOID *Buffer
87 1.1 jakllsch )
88 1.1 jakllsch {
89 1.1 jakllsch uefi_call_wrapper(BS->FreePool, 1, Buffer);
90 1.1 jakllsch }
91 1.1 jakllsch
92 1.1 jakllsch
93 1.1 jakllsch
94 1.1 jakllsch VOID
95 1.1 jakllsch ZeroMem (
96 1.1 jakllsch IN VOID *Buffer,
97 1.1 jakllsch IN UINTN Size
98 1.1 jakllsch )
99 1.1 jakllsch {
100 1.1 jakllsch RtZeroMem (Buffer, Size);
101 1.1 jakllsch }
102 1.1 jakllsch
103 1.1 jakllsch VOID
104 1.1 jakllsch SetMem (
105 1.1 jakllsch IN VOID *Buffer,
106 1.1 jakllsch IN UINTN Size,
107 1.1 jakllsch IN UINT8 Value
108 1.1 jakllsch )
109 1.1 jakllsch {
110 1.1 jakllsch RtSetMem (Buffer, Size, Value);
111 1.1 jakllsch }
112 1.1 jakllsch
113 1.1 jakllsch VOID
114 1.1 jakllsch CopyMem (
115 1.1 jakllsch IN VOID *Dest,
116 1.1 jakllsch IN VOID *Src,
117 1.1 jakllsch IN UINTN len
118 1.1 jakllsch )
119 1.1 jakllsch {
120 1.1 jakllsch RtCopyMem (Dest, Src, len);
121 1.1 jakllsch }
122 1.1 jakllsch
123 1.1 jakllsch INTN
124 1.1 jakllsch CompareMem (
125 1.1 jakllsch IN VOID *Dest,
126 1.1 jakllsch IN VOID *Src,
127 1.1 jakllsch IN UINTN len
128 1.1 jakllsch )
129 1.1 jakllsch {
130 1.1 jakllsch return RtCompareMem (Dest, Src, len);
131 1.1 jakllsch }
132 1.1 jakllsch
133 1.1 jakllsch BOOLEAN
134 1.1 jakllsch GrowBuffer(
135 1.1 jakllsch IN OUT EFI_STATUS *Status,
136 1.1 jakllsch IN OUT VOID **Buffer,
137 1.1 jakllsch IN UINTN BufferSize
138 1.1 jakllsch )
139 1.1 jakllsch /*++
140 1.1 jakllsch
141 1.1 jakllsch Routine Description:
142 1.1 jakllsch
143 1.1 jakllsch Helper function called as part of the code needed
144 1.1 jakllsch to allocate the proper sized buffer for various
145 1.1 jakllsch EFI interfaces.
146 1.1 jakllsch
147 1.1 jakllsch Arguments:
148 1.1 jakllsch
149 1.1 jakllsch Status - Current status
150 1.1 jakllsch
151 1.1 jakllsch Buffer - Current allocated buffer, or NULL
152 1.1 jakllsch
153 1.1 jakllsch BufferSize - Current buffer size needed
154 1.1 jakllsch
155 1.1 jakllsch Returns:
156 1.1 jakllsch
157 1.1 jakllsch TRUE - if the buffer was reallocated and the caller
158 1.1 jakllsch should try the API again.
159 1.1 jakllsch
160 1.1 jakllsch --*/
161 1.1 jakllsch {
162 1.1 jakllsch BOOLEAN TryAgain;
163 1.1 jakllsch
164 1.1 jakllsch //
165 1.1 jakllsch // If this is an initial request, buffer will be null with a new buffer size
166 1.1 jakllsch //
167 1.1 jakllsch
168 1.1 jakllsch if (!*Buffer && BufferSize) {
169 1.1 jakllsch *Status = EFI_BUFFER_TOO_SMALL;
170 1.1 jakllsch }
171 1.1 jakllsch
172 1.1 jakllsch //
173 1.1 jakllsch // If the status code is "buffer too small", resize the buffer
174 1.1 jakllsch //
175 1.1 jakllsch
176 1.1 jakllsch TryAgain = FALSE;
177 1.1 jakllsch if (*Status == EFI_BUFFER_TOO_SMALL) {
178 1.1 jakllsch
179 1.1 jakllsch if (*Buffer) {
180 1.1 jakllsch FreePool (*Buffer);
181 1.1 jakllsch }
182 1.1 jakllsch
183 1.1 jakllsch *Buffer = AllocatePool (BufferSize);
184 1.1 jakllsch
185 1.1 jakllsch if (*Buffer) {
186 1.1 jakllsch TryAgain = TRUE;
187 1.1 jakllsch } else {
188 1.1 jakllsch *Status = EFI_OUT_OF_RESOURCES;
189 1.1 jakllsch }
190 1.1 jakllsch }
191 1.1 jakllsch
192 1.1 jakllsch //
193 1.1 jakllsch // If there's an error, free the buffer
194 1.1 jakllsch //
195 1.1 jakllsch
196 1.1 jakllsch if (!TryAgain && EFI_ERROR(*Status) && *Buffer) {
197 1.1 jakllsch FreePool (*Buffer);
198 1.1 jakllsch *Buffer = NULL;
199 1.1 jakllsch }
200 1.1 jakllsch
201 1.1 jakllsch return TryAgain;
202 1.1 jakllsch }
203 1.1 jakllsch
204 1.1 jakllsch
205 1.1 jakllsch EFI_MEMORY_DESCRIPTOR *
206 1.1 jakllsch LibMemoryMap (
207 1.1 jakllsch OUT UINTN *NoEntries,
208 1.1 jakllsch OUT UINTN *MapKey,
209 1.1 jakllsch OUT UINTN *DescriptorSize,
210 1.1 jakllsch OUT UINT32 *DescriptorVersion
211 1.1 jakllsch )
212 1.1 jakllsch {
213 1.1 jakllsch EFI_STATUS Status;
214 1.1 jakllsch EFI_MEMORY_DESCRIPTOR *Buffer;
215 1.1 jakllsch UINTN BufferSize;
216 1.1 jakllsch
217 1.1 jakllsch //
218 1.1 jakllsch // Initialize for GrowBuffer loop
219 1.1 jakllsch //
220 1.1 jakllsch
221 1.1 jakllsch Buffer = NULL;
222 1.1 jakllsch BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
223 1.1 jakllsch
224 1.1 jakllsch //
225 1.1 jakllsch // Call the real function
226 1.1 jakllsch //
227 1.1 jakllsch
228 1.1 jakllsch while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
229 1.1 jakllsch Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
230 1.1 jakllsch }
231 1.1 jakllsch
232 1.1 jakllsch //
233 1.1 jakllsch // Convert buffer size to NoEntries
234 1.1 jakllsch //
235 1.1 jakllsch
236 1.1 jakllsch if (!EFI_ERROR(Status)) {
237 1.1 jakllsch *NoEntries = BufferSize / *DescriptorSize;
238 1.1 jakllsch }
239 1.1 jakllsch
240 1.1 jakllsch return Buffer;
241 1.1 jakllsch }
242 1.1 jakllsch
243 1.1 jakllsch VOID *
244 1.1 jakllsch LibGetVariableAndSize (
245 1.1 jakllsch IN CHAR16 *Name,
246 1.1 jakllsch IN EFI_GUID *VendorGuid,
247 1.1 jakllsch OUT UINTN *VarSize
248 1.1 jakllsch )
249 1.1 jakllsch {
250 1.1 jakllsch EFI_STATUS Status;
251 1.1 jakllsch VOID *Buffer;
252 1.1 jakllsch UINTN BufferSize;
253 1.1 jakllsch
254 1.1 jakllsch //
255 1.1 jakllsch // Initialize for GrowBuffer loop
256 1.1 jakllsch //
257 1.1 jakllsch
258 1.1 jakllsch Buffer = NULL;
259 1.1 jakllsch BufferSize = 100;
260 1.1 jakllsch
261 1.1 jakllsch //
262 1.1 jakllsch // Call the real function
263 1.1 jakllsch //
264 1.1 jakllsch
265 1.1 jakllsch while (GrowBuffer (&Status, &Buffer, BufferSize)) {
266 1.1 jakllsch Status = uefi_call_wrapper(
267 1.1 jakllsch RT->GetVariable,
268 1.1 jakllsch 5,
269 1.1 jakllsch Name,
270 1.1 jakllsch VendorGuid,
271 1.1 jakllsch NULL,
272 1.1 jakllsch &BufferSize,
273 1.1 jakllsch Buffer
274 1.1 jakllsch );
275 1.1 jakllsch }
276 1.1 jakllsch if (Buffer) {
277 1.1 jakllsch *VarSize = BufferSize;
278 1.1 jakllsch } else {
279 1.1 jakllsch *VarSize = 0;
280 1.1 jakllsch }
281 1.1 jakllsch return Buffer;
282 1.1 jakllsch }
283 1.1 jakllsch
284 1.1 jakllsch VOID *
285 1.1 jakllsch LibGetVariable (
286 1.1 jakllsch IN CHAR16 *Name,
287 1.1 jakllsch IN EFI_GUID *VendorGuid
288 1.1 jakllsch )
289 1.1 jakllsch {
290 1.1 jakllsch UINTN VarSize;
291 1.1 jakllsch
292 1.1 jakllsch return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
293 1.1 jakllsch }
294 1.1 jakllsch
295 1.1 jakllsch EFI_STATUS
296 1.1 jakllsch LibDeleteVariable (
297 1.1 jakllsch IN CHAR16 *VarName,
298 1.1 jakllsch IN EFI_GUID *VarGuid
299 1.1 jakllsch )
300 1.1 jakllsch {
301 1.1 jakllsch VOID *VarBuf;
302 1.1 jakllsch EFI_STATUS Status;
303 1.1 jakllsch
304 1.1 jakllsch VarBuf = LibGetVariable(VarName,VarGuid);
305 1.1 jakllsch
306 1.1 jakllsch Status = EFI_NOT_FOUND;
307 1.1 jakllsch
308 1.1 jakllsch if (VarBuf) {
309 1.1 jakllsch //
310 1.1 jakllsch // Delete variable from Storage
311 1.1 jakllsch //
312 1.1 jakllsch Status = uefi_call_wrapper(
313 1.1 jakllsch RT->SetVariable,
314 1.1 jakllsch 5,
315 1.1 jakllsch VarName, VarGuid,
316 1.1 jakllsch EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
317 1.1 jakllsch 0, NULL
318 1.1 jakllsch );
319 1.1 jakllsch ASSERT (!EFI_ERROR(Status));
320 1.1 jakllsch FreePool(VarBuf);
321 1.1 jakllsch }
322 1.1 jakllsch
323 1.1 jakllsch return (Status);
324 1.1 jakllsch }
325 1.1 jakllsch
326 1.1 jakllsch EFI_STATUS
327 1.1 jakllsch LibInsertToTailOfBootOrder (
328 1.1 jakllsch IN UINT16 BootOption,
329 1.1 jakllsch IN BOOLEAN OnlyInsertIfEmpty
330 1.1 jakllsch )
331 1.1 jakllsch {
332 1.1 jakllsch UINT16 *BootOptionArray;
333 1.1 jakllsch UINT16 *NewBootOptionArray;
334 1.1 jakllsch UINTN VarSize;
335 1.1 jakllsch UINTN Index;
336 1.1 jakllsch EFI_STATUS Status;
337 1.1 jakllsch
338 1.1 jakllsch BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
339 1.1 jakllsch if (VarSize != 0 && OnlyInsertIfEmpty) {
340 1.1 jakllsch if (BootOptionArray) {
341 1.1 jakllsch FreePool (BootOptionArray);
342 1.1 jakllsch }
343 1.1 jakllsch return EFI_UNSUPPORTED;
344 1.1 jakllsch }
345 1.1 jakllsch
346 1.1 jakllsch VarSize += sizeof(UINT16);
347 1.1 jakllsch NewBootOptionArray = AllocatePool (VarSize);
348 1.1 jakllsch
349 1.1 jakllsch for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
350 1.1 jakllsch NewBootOptionArray[Index] = BootOptionArray[Index];
351 1.1 jakllsch }
352 1.1 jakllsch //
353 1.1 jakllsch // Insert in the tail of the array
354 1.1 jakllsch //
355 1.1 jakllsch NewBootOptionArray[Index] = BootOption;
356 1.1 jakllsch
357 1.1 jakllsch Status = uefi_call_wrapper(
358 1.1 jakllsch RT->SetVariable,
359 1.1 jakllsch 5,
360 1.1 jakllsch VarBootOrder, &EfiGlobalVariable,
361 1.1 jakllsch EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
362 1.1 jakllsch VarSize, (VOID*) NewBootOptionArray
363 1.1 jakllsch );
364 1.1 jakllsch
365 1.1 jakllsch if (NewBootOptionArray) {
366 1.1 jakllsch FreePool (NewBootOptionArray);
367 1.1 jakllsch }
368 1.1 jakllsch if (BootOptionArray) {
369 1.1 jakllsch FreePool (BootOptionArray);
370 1.1 jakllsch }
371 1.1 jakllsch return Status;
372 1.1 jakllsch }
373 1.1 jakllsch
374 1.1 jakllsch
375 1.1 jakllsch BOOLEAN
376 1.1 jakllsch ValidMBR(
377 1.1 jakllsch IN MASTER_BOOT_RECORD *Mbr,
378 1.1 jakllsch IN EFI_BLOCK_IO *BlkIo
379 1.1 jakllsch )
380 1.1 jakllsch {
381 1.1 jakllsch UINT32 StartingLBA, EndingLBA;
382 1.1 jakllsch UINT32 NewEndingLBA;
383 1.1 jakllsch INTN i, j;
384 1.1 jakllsch BOOLEAN ValidMbr;
385 1.1 jakllsch
386 1.1 jakllsch if (Mbr->Signature != MBR_SIGNATURE) {
387 1.1 jakllsch //
388 1.1 jakllsch // The BPB also has this signature, so it can not be used alone.
389 1.1 jakllsch //
390 1.1 jakllsch return FALSE;
391 1.1 jakllsch }
392 1.1 jakllsch
393 1.1 jakllsch ValidMbr = FALSE;
394 1.1 jakllsch for (i=0; i<MAX_MBR_PARTITIONS; i++) {
395 1.1 jakllsch if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
396 1.1 jakllsch continue;
397 1.1 jakllsch }
398 1.1 jakllsch ValidMbr = TRUE;
399 1.1 jakllsch StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
400 1.1 jakllsch EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
401 1.1 jakllsch if (EndingLBA > BlkIo->Media->LastBlock) {
402 1.1 jakllsch //
403 1.1 jakllsch // Compatability Errata:
404 1.1 jakllsch // Some systems try to hide drive space with thier INT 13h driver
405 1.1 jakllsch // This does not hide space from the OS driver. This means the MBR
406 1.1 jakllsch // that gets created from DOS is smaller than the MBR created from
407 1.1 jakllsch // a real OS (NT & Win98). This leads to BlkIo->LastBlock being
408 1.1 jakllsch // wrong on some systems FDISKed by the OS.
409 1.1 jakllsch //
410 1.1 jakllsch //
411 1.1 jakllsch if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
412 1.1 jakllsch //
413 1.1 jakllsch // If this is a very small device then trust the BlkIo->LastBlock
414 1.1 jakllsch //
415 1.1 jakllsch return FALSE;
416 1.1 jakllsch }
417 1.1 jakllsch
418 1.1 jakllsch if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
419 1.1 jakllsch return FALSE;
420 1.1 jakllsch }
421 1.1 jakllsch
422 1.1 jakllsch }
423 1.1 jakllsch for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
424 1.1 jakllsch if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
425 1.1 jakllsch continue;
426 1.1 jakllsch }
427 1.1 jakllsch if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
428 1.1 jakllsch EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) {
429 1.1 jakllsch //
430 1.1 jakllsch // The Start of this region overlaps with the i'th region
431 1.1 jakllsch //
432 1.1 jakllsch return FALSE;
433 1.1 jakllsch }
434 1.1 jakllsch NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
435 1.1 jakllsch if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
436 1.1 jakllsch //
437 1.1 jakllsch // The End of this region overlaps with the i'th region
438 1.1 jakllsch //
439 1.1 jakllsch return FALSE;
440 1.1 jakllsch }
441 1.1 jakllsch }
442 1.1 jakllsch }
443 1.1 jakllsch //
444 1.1 jakllsch // Non of the regions overlapped so MBR is O.K.
445 1.1 jakllsch //
446 1.1 jakllsch return ValidMbr;
447 1.1 jakllsch }
448 1.1 jakllsch
449 1.1 jakllsch
450 1.1 jakllsch UINT8
451 1.1 jakllsch DecimaltoBCD(
452 1.1 jakllsch IN UINT8 DecValue
453 1.1 jakllsch )
454 1.1 jakllsch {
455 1.1 jakllsch return RtDecimaltoBCD (DecValue);
456 1.1 jakllsch }
457 1.1 jakllsch
458 1.1 jakllsch
459 1.1 jakllsch UINT8
460 1.1 jakllsch BCDtoDecimal(
461 1.1 jakllsch IN UINT8 BcdValue
462 1.1 jakllsch )
463 1.1 jakllsch {
464 1.1 jakllsch return RtBCDtoDecimal (BcdValue);
465 1.1 jakllsch }
466 1.1 jakllsch
467 1.1 jakllsch EFI_STATUS
468 1.1 jakllsch LibGetSystemConfigurationTable(
469 1.1 jakllsch IN EFI_GUID *TableGuid,
470 1.1 jakllsch IN OUT VOID **Table
471 1.1 jakllsch )
472 1.1 jakllsch
473 1.1 jakllsch {
474 1.1 jakllsch UINTN Index;
475 1.1 jakllsch
476 1.1 jakllsch for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
477 1.1 jakllsch if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
478 1.1 jakllsch *Table = ST->ConfigurationTable[Index].VendorTable;
479 1.1 jakllsch return EFI_SUCCESS;
480 1.1 jakllsch }
481 1.1 jakllsch }
482 1.1 jakllsch return EFI_NOT_FOUND;
483 1.1 jakllsch }
484 1.1 jakllsch
485 1.1 jakllsch
486 1.1 jakllsch CHAR16 *
487 1.1 jakllsch LibGetUiString (
488 1.1 jakllsch IN EFI_HANDLE Handle,
489 1.1 jakllsch IN UI_STRING_TYPE StringType,
490 1.1 jakllsch IN ISO_639_2 *LangCode,
491 1.1 jakllsch IN BOOLEAN ReturnDevicePathStrOnMismatch
492 1.1 jakllsch )
493 1.1 jakllsch {
494 1.1 jakllsch UI_INTERFACE *Ui;
495 1.1 jakllsch UI_STRING_TYPE Index;
496 1.1 jakllsch UI_STRING_ENTRY *Array;
497 1.1 jakllsch EFI_STATUS Status;
498 1.1 jakllsch
499 1.1 jakllsch Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
500 1.1 jakllsch if (EFI_ERROR(Status)) {
501 1.1 jakllsch return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
502 1.1 jakllsch }
503 1.1 jakllsch
504 1.1 jakllsch //
505 1.1 jakllsch // Skip the first strings
506 1.1 jakllsch //
507 1.1 jakllsch for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
508 1.1 jakllsch while (Array->LangCode) {
509 1.1 jakllsch Array++;
510 1.1 jakllsch }
511 1.1 jakllsch }
512 1.1 jakllsch
513 1.1 jakllsch //
514 1.1 jakllsch // Search for the match
515 1.1 jakllsch //
516 1.1 jakllsch while (Array->LangCode) {
517 1.1 jakllsch if (strcmpa (Array->LangCode, LangCode) == 0) {
518 1.1 jakllsch return Array->UiString;
519 1.1 jakllsch }
520 1.1 jakllsch }
521 1.1 jakllsch return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
522 1.1 jakllsch }
523