]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/FatPei/FatLiteLib.c
FatPkg: Apply uncrustify changes
[mirror_edk2.git] / FatPkg / FatPei / FatLiteLib.c
CommitLineData
2f4dfa84
JJ
1/** @file\r
2 General purpose supporting routines for FAT recovery PEIM\r
3\r
e38f26a2 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
2f4dfa84 5\r
eb6cb4ce 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
2f4dfa84
JJ
7\r
8**/\r
9\r
10#include "FatLitePeim.h"\r
11\r
2f4dfa84
JJ
12#define CHAR_FAT_VALID 0x01\r
13\r
2f4dfa84
JJ
14/**\r
15 Converts a union code character to upper case.\r
16 This functions converts a unicode character to upper case.\r
17 If the input Letter is not a lower-cased letter,\r
18 the original value is returned.\r
19\r
e38f26a2 20 @param Letter The input unicode character.\r
2f4dfa84
JJ
21\r
22 @return The upper cased letter.\r
23\r
24**/\r
25CHAR16\r
26ToUpper (\r
bcdcc416 27 IN CHAR16 Letter\r
2f4dfa84
JJ
28 )\r
29{\r
bcdcc416
MK
30 if (('a' <= Letter) && (Letter <= 'z')) {\r
31 Letter = (CHAR16)(Letter - 0x20);\r
2f4dfa84
JJ
32 }\r
33\r
34 return Letter;\r
35}\r
36\r
2f4dfa84
JJ
37/**\r
38 Reads a block of data from the block device by calling\r
39 underlying Block I/O service.\r
40\r
e38f26a2
LG
41 @param PrivateData Global memory map for accessing global variables\r
42 @param BlockDeviceNo The index for the block device number.\r
43 @param Lba The logic block address to read data from.\r
44 @param BufferSize The size of data in byte to read.\r
45 @param Buffer The buffer of the\r
2f4dfa84 46\r
e38f26a2
LG
47 @retval EFI_DEVICE_ERROR The specified block device number exceeds the maximum\r
48 device number.\r
49 @retval EFI_DEVICE_ERROR The maximum address has exceeded the maximum address\r
2f4dfa84
JJ
50 of the block device.\r
51\r
52**/\r
53EFI_STATUS\r
54FatReadBlock (\r
bcdcc416
MK
55 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
56 IN UINTN BlockDeviceNo,\r
57 IN EFI_PEI_LBA Lba,\r
58 IN UINTN BufferSize,\r
59 OUT VOID *Buffer\r
2f4dfa84
JJ
60 )\r
61{\r
62 EFI_STATUS Status;\r
63 PEI_FAT_BLOCK_DEVICE *BlockDev;\r
64\r
65 if (BlockDeviceNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
66 return EFI_DEVICE_ERROR;\r
67 }\r
68\r
bcdcc416
MK
69 Status = EFI_SUCCESS;\r
70 BlockDev = &(PrivateData->BlockDevice[BlockDeviceNo]);\r
2f4dfa84
JJ
71\r
72 if (BufferSize > MultU64x32 (BlockDev->LastBlock - Lba + 1, BlockDev->BlockSize)) {\r
73 return EFI_DEVICE_ERROR;\r
74 }\r
75\r
76 if (!BlockDev->Logical) {\r
77 //\r
78 // Status = BlockDev->ReadFunc\r
79 // (PrivateData->PeiServices, BlockDev->PhysicalDevNo, Lba, BufferSize, Buffer);\r
80 //\r
8a467be1
FT
81 if (BlockDev->BlockIo2 != NULL) {\r
82 Status = BlockDev->BlockIo2->ReadBlocks (\r
bcdcc416
MK
83 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
84 BlockDev->BlockIo2,\r
85 BlockDev->PhysicalDevNo,\r
86 Lba,\r
87 BufferSize,\r
88 Buffer\r
89 );\r
90 } else {\r
91 Status = BlockDev->BlockIo->ReadBlocks (\r
92 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
93 BlockDev->BlockIo,\r
8a467be1
FT
94 BlockDev->PhysicalDevNo,\r
95 Lba,\r
96 BufferSize,\r
97 Buffer\r
98 );\r
8a467be1 99 }\r
2f4dfa84
JJ
100 } else {\r
101 Status = FatReadDisk (\r
bcdcc416
MK
102 PrivateData,\r
103 BlockDev->ParentDevNo,\r
104 BlockDev->StartingPos + MultU64x32 (Lba, BlockDev->BlockSize),\r
105 BufferSize,\r
106 Buffer\r
107 );\r
2f4dfa84
JJ
108 }\r
109\r
110 return Status;\r
111}\r
112\r
2f4dfa84
JJ
113/**\r
114 Find a cache block designated to specific Block device and Lba.\r
115 If not found, invalidate an oldest one and use it. (LRU cache)\r
116\r
e38f26a2
LG
117 @param PrivateData the global memory map.\r
118 @param BlockDeviceNo the Block device.\r
119 @param Lba the Logical Block Address\r
120 @param CachePtr Ptr to the starting address of the memory holding the\r
121 data;\r
2f4dfa84
JJ
122\r
123 @retval EFI_SUCCESS The function completed successfully.\r
124 @retval EFI_DEVICE_ERROR Something error while accessing media.\r
125\r
126**/\r
127EFI_STATUS\r
128FatGetCacheBlock (\r
129 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
130 IN UINTN BlockDeviceNo,\r
131 IN UINT64 Lba,\r
132 OUT CHAR8 **CachePtr\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 PEI_FAT_CACHE_BUFFER *CacheBuffer;\r
137 INTN Index;\r
138 STATIC UINT8 Seed;\r
139\r
140 Status = EFI_SUCCESS;\r
141 CacheBuffer = NULL;\r
142\r
143 //\r
144 // go through existing cache buffers\r
145 //\r
146 for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {\r
147 CacheBuffer = &(PrivateData->CacheBuffer[Index]);\r
bcdcc416 148 if (CacheBuffer->Valid && (CacheBuffer->BlockDeviceNo == BlockDeviceNo) && (CacheBuffer->Lba == Lba)) {\r
2f4dfa84
JJ
149 break;\r
150 }\r
151 }\r
152\r
153 if (Index < PEI_FAT_CACHE_SIZE) {\r
bcdcc416 154 *CachePtr = (CHAR8 *)CacheBuffer->Buffer;\r
2f4dfa84
JJ
155 return EFI_SUCCESS;\r
156 }\r
bcdcc416 157\r
2f4dfa84
JJ
158 //\r
159 // We have to find an invalid cache buffer\r
160 //\r
161 for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {\r
162 if (!PrivateData->CacheBuffer[Index].Valid) {\r
163 break;\r
164 }\r
165 }\r
bcdcc416 166\r
2f4dfa84
JJ
167 //\r
168 // Use the cache buffer\r
169 //\r
170 if (Index == PEI_FAT_CACHE_SIZE) {\r
171 Index = (Seed++) % PEI_FAT_CACHE_SIZE;\r
172 }\r
e38f26a2 173\r
2f4dfa84 174 //\r
e38f26a2 175 // Current device ID should be less than maximum device ID.\r
2f4dfa84
JJ
176 //\r
177 if (BlockDeviceNo >= PEI_FAT_MAX_BLOCK_DEVICE) {\r
178 return EFI_DEVICE_ERROR;\r
179 }\r
180\r
bcdcc416 181 CacheBuffer = &(PrivateData->CacheBuffer[Index]);\r
2f4dfa84 182\r
bcdcc416
MK
183 CacheBuffer->BlockDeviceNo = BlockDeviceNo;\r
184 CacheBuffer->Lba = Lba;\r
185 CacheBuffer->Size = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;\r
2f4dfa84
JJ
186\r
187 //\r
188 // Read in the data\r
189 //\r
190 Status = FatReadBlock (\r
bcdcc416
MK
191 PrivateData,\r
192 BlockDeviceNo,\r
193 Lba,\r
194 CacheBuffer->Size,\r
195 CacheBuffer->Buffer\r
196 );\r
2f4dfa84
JJ
197 if (EFI_ERROR (Status)) {\r
198 return EFI_DEVICE_ERROR;\r
199 }\r
200\r
bcdcc416
MK
201 CacheBuffer->Valid = TRUE;\r
202 *CachePtr = (CHAR8 *)CacheBuffer->Buffer;\r
2f4dfa84
JJ
203\r
204 return Status;\r
205}\r
206\r
2f4dfa84
JJ
207/**\r
208 Disk reading.\r
209\r
e38f26a2
LG
210 @param PrivateData the global memory map;\r
211 @param BlockDeviceNo the block device to read;\r
212 @param StartingAddress the starting address.\r
213 @param Size the amount of data to read.\r
214 @param Buffer the buffer holding the data\r
2f4dfa84
JJ
215\r
216 @retval EFI_SUCCESS The function completed successfully.\r
217 @retval EFI_DEVICE_ERROR Something error.\r
218\r
219**/\r
220EFI_STATUS\r
221FatReadDisk (\r
222 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
223 IN UINTN BlockDeviceNo,\r
224 IN UINT64 StartingAddress,\r
225 IN UINTN Size,\r
226 OUT VOID *Buffer\r
227 )\r
228{\r
229 EFI_STATUS Status;\r
230 UINT32 BlockSize;\r
231 CHAR8 *BufferPtr;\r
232 CHAR8 *CachePtr;\r
233 UINT32 Offset;\r
234 UINT64 Lba;\r
235 UINT64 OverRunLba;\r
236 UINTN Amount;\r
237\r
238 Status = EFI_SUCCESS;\r
239 BufferPtr = Buffer;\r
240 BlockSize = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;\r
241\r
242 //\r
243 // Read underrun\r
244 //\r
bcdcc416
MK
245 Lba = DivU64x32Remainder (StartingAddress, BlockSize, &Offset);\r
246 Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, Lba, &CachePtr);\r
2f4dfa84
JJ
247 if (EFI_ERROR (Status)) {\r
248 return EFI_DEVICE_ERROR;\r
249 }\r
250\r
251 Amount = Size < (BlockSize - Offset) ? Size : (BlockSize - Offset);\r
252 CopyMem (BufferPtr, CachePtr + Offset, Amount);\r
253\r
254 if (Size == Amount) {\r
255 return EFI_SUCCESS;\r
256 }\r
257\r
bcdcc416
MK
258 Size -= Amount;\r
259 BufferPtr += Amount;\r
2f4dfa84 260 StartingAddress += Amount;\r
bcdcc416 261 Lba += 1;\r
2f4dfa84
JJ
262\r
263 //\r
264 // Read aligned parts\r
265 //\r
266 OverRunLba = Lba + DivU64x32Remainder (Size, BlockSize, &Offset);\r
267\r
bcdcc416 268 Size -= Offset;\r
2f4dfa84
JJ
269 Status = FatReadBlock (PrivateData, BlockDeviceNo, Lba, Size, BufferPtr);\r
270 if (EFI_ERROR (Status)) {\r
271 return EFI_DEVICE_ERROR;\r
272 }\r
273\r
274 BufferPtr += Size;\r
275\r
276 //\r
277 // Read overrun\r
278 //\r
279 if (Offset != 0) {\r
280 Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, OverRunLba, &CachePtr);\r
281 if (EFI_ERROR (Status)) {\r
282 return EFI_DEVICE_ERROR;\r
283 }\r
284\r
285 CopyMem (BufferPtr, CachePtr, Offset);\r
286 }\r
287\r
288 return Status;\r
289}\r
290\r
2f4dfa84
JJ
291/**\r
292 This version is different from the version in Unicode collation\r
293 protocol in that this version strips off trailing blanks.\r
294 Converts an 8.3 FAT file name using an OEM character set\r
295 to a Null-terminated Unicode string.\r
296 Here does not expand DBCS FAT chars.\r
297\r
e38f26a2
LG
298 @param FatSize The size of the string Fat in bytes.\r
299 @param Fat A pointer to a Null-terminated string that contains\r
300 an 8.3 file name using an OEM character set.\r
301 @param Str A pointer to a Null-terminated Unicode string. The\r
302 string must be allocated in advance to hold FatSize\r
2f4dfa84
JJ
303 Unicode characters\r
304\r
305**/\r
306VOID\r
307EngFatToStr (\r
bcdcc416
MK
308 IN UINTN FatSize,\r
309 IN CHAR8 *Fat,\r
310 OUT CHAR16 *Str\r
2f4dfa84
JJ
311 )\r
312{\r
313 CHAR16 *String;\r
314\r
315 String = Str;\r
316 //\r
317 // No DBCS issues, just expand and add null terminate to end of string\r
318 //\r
319 while (*Fat != 0 && FatSize != 0) {\r
3ba5368d
SZ
320 if (*Fat == ' ') {\r
321 break;\r
322 }\r
bcdcc416
MK
323\r
324 *String = *Fat;\r
325 String += 1;\r
326 Fat += 1;\r
2f4dfa84 327 FatSize -= 1;\r
2f4dfa84 328 }\r
3ba5368d
SZ
329\r
330 *String = 0;\r
2f4dfa84
JJ
331}\r
332\r
2f4dfa84
JJ
333/**\r
334 Performs a case-insensitive comparison of two Null-terminated Unicode strings.\r
335\r
e38f26a2
LG
336 @param PrivateData Global memory map for accessing global variables\r
337 @param Str1 First string to perform case insensitive comparison.\r
2f4dfa84
JJ
338 @param Str2 Second string to perform case insensitive comparison.\r
339\r
340**/\r
341BOOLEAN\r
342EngStriColl (\r
343 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
344 IN CHAR16 *Str1,\r
345 IN CHAR16 *Str2\r
346 )\r
347{\r
348 CHAR16 UpperS1;\r
349 CHAR16 UpperS2;\r
350\r
351 UpperS1 = ToUpper (*Str1);\r
352 UpperS2 = ToUpper (*Str2);\r
353 while (*Str1 != 0) {\r
354 if (UpperS1 != UpperS2) {\r
355 return FALSE;\r
356 }\r
357\r
358 Str1++;\r
359 Str2++;\r
360 UpperS1 = ToUpper (*Str1);\r
361 UpperS2 = ToUpper (*Str2);\r
362 }\r
363\r
bcdcc416 364 return (BOOLEAN)((*Str2 != 0) ? FALSE : TRUE);\r
2f4dfa84 365}\r