]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/FatPei/FatLiteLib.c
1. Expand and add null terminate to end of string like function comments said in...
[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
3ba5368d 4Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
2f4dfa84
JJ
5\r
6This program and the accompanying materials are licensed and made available\r
7under the terms and conditions of the BSD License which accompanies this\r
8distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "FatLitePeim.h"\r
17\r
18\r
19#define CHAR_FAT_VALID 0x01\r
20\r
21\r
22/**\r
23 Converts a union code character to upper case.\r
24 This functions converts a unicode character to upper case.\r
25 If the input Letter is not a lower-cased letter,\r
26 the original value is returned.\r
27\r
28 @param Letter The input unicode character. \r
29\r
30 @return The upper cased letter.\r
31\r
32**/\r
33CHAR16\r
34ToUpper (\r
35 IN CHAR16 Letter\r
36 )\r
37{\r
38 if ('a' <= Letter && Letter <= 'z') {\r
39 Letter = (CHAR16) (Letter - 0x20);\r
40 }\r
41\r
42 return Letter;\r
43}\r
44\r
45\r
46/**\r
47 Reads a block of data from the block device by calling\r
48 underlying Block I/O service.\r
49\r
50 @param PrivateData Global memory map for accessing global variables \r
51 @param BlockDeviceNo The index for the block device number. \r
52 @param Lba The logic block address to read data from. \r
53 @param BufferSize The size of data in byte to read. \r
54 @param Buffer The buffer of the \r
55\r
56 @retval EFI_DEVICE_ERROR The specified block device number exceeds the maximum \r
57 device number. \r
58 @retval EFI_DEVICE_ERROR The maximum address has exceeded the maximum address \r
59 of the block device.\r
60\r
61**/\r
62EFI_STATUS\r
63FatReadBlock (\r
64 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
65 IN UINTN BlockDeviceNo,\r
66 IN EFI_PEI_LBA Lba,\r
67 IN UINTN BufferSize,\r
68 OUT VOID *Buffer\r
69 )\r
70{\r
71 EFI_STATUS Status;\r
72 PEI_FAT_BLOCK_DEVICE *BlockDev;\r
73\r
74 if (BlockDeviceNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
75 return EFI_DEVICE_ERROR;\r
76 }\r
77\r
78 Status = EFI_SUCCESS;\r
79 BlockDev = &(PrivateData->BlockDevice[BlockDeviceNo]);\r
80\r
81 if (BufferSize > MultU64x32 (BlockDev->LastBlock - Lba + 1, BlockDev->BlockSize)) {\r
82 return EFI_DEVICE_ERROR;\r
83 }\r
84\r
85 if (!BlockDev->Logical) {\r
86 //\r
87 // Status = BlockDev->ReadFunc\r
88 // (PrivateData->PeiServices, BlockDev->PhysicalDevNo, Lba, BufferSize, Buffer);\r
89 //\r
90 Status = BlockDev->BlockIo->ReadBlocks (\r
91 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
92 BlockDev->BlockIo,\r
93 BlockDev->PhysicalDevNo,\r
94 Lba,\r
95 BufferSize,\r
96 Buffer\r
97 );\r
98\r
99 } else {\r
100 Status = FatReadDisk (\r
101 PrivateData,\r
102 BlockDev->ParentDevNo,\r
103 BlockDev->StartingPos + MultU64x32 (Lba, BlockDev->BlockSize),\r
104 BufferSize,\r
105 Buffer\r
106 );\r
107 }\r
108\r
109 return Status;\r
110}\r
111\r
112\r
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
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
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
148 if (CacheBuffer->Valid && CacheBuffer->BlockDeviceNo == BlockDeviceNo && CacheBuffer->Lba == Lba) {\r
149 break;\r
150 }\r
151 }\r
152\r
153 if (Index < PEI_FAT_CACHE_SIZE) {\r
154 *CachePtr = (CHAR8 *) CacheBuffer->Buffer;\r
155 return EFI_SUCCESS;\r
156 }\r
157 //\r
158 // We have to find an invalid cache buffer\r
159 //\r
160 for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {\r
161 if (!PrivateData->CacheBuffer[Index].Valid) {\r
162 break;\r
163 }\r
164 }\r
165 //\r
166 // Use the cache buffer\r
167 //\r
168 if (Index == PEI_FAT_CACHE_SIZE) {\r
169 Index = (Seed++) % PEI_FAT_CACHE_SIZE;\r
170 }\r
171 \r
172 //\r
173 // Current device ID should be less than maximum device ID. \r
174 //\r
175 if (BlockDeviceNo >= PEI_FAT_MAX_BLOCK_DEVICE) {\r
176 return EFI_DEVICE_ERROR;\r
177 }\r
178\r
179 CacheBuffer = &(PrivateData->CacheBuffer[Index]);\r
180\r
181 CacheBuffer->BlockDeviceNo = BlockDeviceNo;\r
182 CacheBuffer->Lba = Lba;\r
183 CacheBuffer->Size = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;\r
184\r
185 //\r
186 // Read in the data\r
187 //\r
188 Status = FatReadBlock (\r
189 PrivateData,\r
190 BlockDeviceNo,\r
191 Lba,\r
192 CacheBuffer->Size,\r
193 CacheBuffer->Buffer\r
194 );\r
195 if (EFI_ERROR (Status)) {\r
196 return EFI_DEVICE_ERROR;\r
197 }\r
198\r
199 CacheBuffer->Valid = TRUE;\r
200 *CachePtr = (CHAR8 *) CacheBuffer->Buffer;\r
201\r
202 return Status;\r
203}\r
204\r
205\r
206/**\r
207 Disk reading.\r
208\r
209 @param PrivateData the global memory map; \r
210 @param BlockDeviceNo the block device to read; \r
211 @param StartingAddress the starting address. \r
212 @param Size the amount of data to read. \r
213 @param Buffer the buffer holding the data \r
214\r
215 @retval EFI_SUCCESS The function completed successfully.\r
216 @retval EFI_DEVICE_ERROR Something error.\r
217\r
218**/\r
219EFI_STATUS\r
220FatReadDisk (\r
221 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
222 IN UINTN BlockDeviceNo,\r
223 IN UINT64 StartingAddress,\r
224 IN UINTN Size,\r
225 OUT VOID *Buffer\r
226 )\r
227{\r
228 EFI_STATUS Status;\r
229 UINT32 BlockSize;\r
230 CHAR8 *BufferPtr;\r
231 CHAR8 *CachePtr;\r
232 UINT32 Offset;\r
233 UINT64 Lba;\r
234 UINT64 OverRunLba;\r
235 UINTN Amount;\r
236\r
237 Status = EFI_SUCCESS;\r
238 BufferPtr = Buffer;\r
239 BlockSize = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;\r
240\r
241 //\r
242 // Read underrun\r
243 //\r
244 Lba = DivU64x32Remainder (StartingAddress, BlockSize, &Offset);\r
245 Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, Lba, &CachePtr);\r
246 if (EFI_ERROR (Status)) {\r
247 return EFI_DEVICE_ERROR;\r
248 }\r
249\r
250 Amount = Size < (BlockSize - Offset) ? Size : (BlockSize - Offset);\r
251 CopyMem (BufferPtr, CachePtr + Offset, Amount);\r
252\r
253 if (Size == Amount) {\r
254 return EFI_SUCCESS;\r
255 }\r
256\r
257 Size -= Amount;\r
258 BufferPtr += Amount;\r
259 StartingAddress += Amount;\r
260 Lba += 1;\r
261\r
262 //\r
263 // Read aligned parts\r
264 //\r
265 OverRunLba = Lba + DivU64x32Remainder (Size, BlockSize, &Offset);\r
266\r
267 Size -= Offset;\r
268 Status = FatReadBlock (PrivateData, BlockDeviceNo, Lba, Size, BufferPtr);\r
269 if (EFI_ERROR (Status)) {\r
270 return EFI_DEVICE_ERROR;\r
271 }\r
272\r
273 BufferPtr += Size;\r
274\r
275 //\r
276 // Read overrun\r
277 //\r
278 if (Offset != 0) {\r
279 Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, OverRunLba, &CachePtr);\r
280 if (EFI_ERROR (Status)) {\r
281 return EFI_DEVICE_ERROR;\r
282 }\r
283\r
284 CopyMem (BufferPtr, CachePtr, Offset);\r
285 }\r
286\r
287 return Status;\r
288}\r
289\r
290\r
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
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
303 Unicode characters\r
304\r
305**/\r
306VOID\r
307EngFatToStr (\r
308 IN UINTN FatSize,\r
309 IN CHAR8 *Fat,\r
310 OUT CHAR16 *Str\r
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
2f4dfa84
JJ
323 *String = *Fat;\r
324 String += 1;\r
325 Fat += 1;\r
326 FatSize -= 1;\r
2f4dfa84 327 }\r
3ba5368d
SZ
328\r
329 *String = 0;\r
2f4dfa84
JJ
330}\r
331\r
332\r
333/**\r
334 Performs a case-insensitive comparison of two Null-terminated Unicode strings.\r
335\r
336 @param PrivateData Global memory map for accessing global variables \r
337 @param Str1 First string to perform case insensitive comparison. \r
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
364 return (BOOLEAN) ((*Str2 != 0) ? FALSE : TRUE);\r
365}\r