]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - DuetPkg/FSVariable/FileStorage.c
CryptoPkg: INF/DEC file updates to EDK II packages
[mirror_edk2.git] / DuetPkg / FSVariable / FileStorage.c
... / ...
CommitLineData
1/*++\r
2\r
3Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 FileStorage.c\r
15\r
16Abstract:\r
17\r
18 handles variable store/reads on file\r
19\r
20Revision History\r
21\r
22--*/\r
23#include "FSVariable.h"\r
24\r
25VOID *mSFSRegistration;\r
26\r
27//\r
28// Prototypes\r
29//\r
30\r
31VOID\r
32EFIAPI\r
33OnVirtualAddressChangeFs (\r
34 IN EFI_EVENT Event,\r
35 IN VOID *Context\r
36 );\r
37\r
38EFI_STATUS\r
39EFIAPI\r
40FileEraseStore(\r
41 IN VARIABLE_STORAGE *This\r
42 );\r
43\r
44EFI_STATUS\r
45EFIAPI\r
46FileWriteStore (\r
47 IN VARIABLE_STORAGE *This,\r
48 IN UINTN Offset,\r
49 IN UINTN BufferSize,\r
50 IN VOID *Buffer\r
51 );\r
52\r
53EFI_STATUS\r
54OpenStore (\r
55 IN EFI_DEVICE_PATH_PROTOCOL *Device,\r
56 IN CHAR16 *FilePathName,\r
57 IN UINT64 OpenMode,\r
58 OUT EFI_FILE_PROTOCOL **File\r
59 );\r
60\r
61//\r
62// Implementation below:\r
63//\r
64VOID\r
65FileClose (\r
66 IN EFI_FILE_PROTOCOL *File\r
67 )\r
68{\r
69 EFI_STATUS Status;\r
70\r
71 Status = File->Flush (File);\r
72 ASSERT_EFI_ERROR (Status);\r
73\r
74 Status = File->Close (File);\r
75 ASSERT_EFI_ERROR (Status);\r
76}\r
77\r
78EFI_STATUS\r
79CheckStore (\r
80 IN EFI_HANDLE SimpleFileSystemHandle,\r
81 IN UINT32 VolumeId,\r
82 OUT EFI_DEVICE_PATH_PROTOCOL **Device\r
83 )\r
84{\r
85#define BLOCK_SIZE 0x200\r
86#define FAT16_VOLUME_ID_OFFSET 39\r
87#define FAT32_VOLUME_ID_OFFSET 67\r
88 EFI_STATUS Status;\r
89 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
90 UINT8 BootSector[BLOCK_SIZE];\r
91\r
92 *Device = NULL;\r
93 Status = gBS->HandleProtocol (\r
94 SimpleFileSystemHandle,\r
95 &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem\r
96 (VOID*)&BlkIo\r
97 );\r
98\r
99 if (EFI_ERROR (Status)) {\r
100 goto ErrHandle;\r
101 }\r
102 if (!BlkIo->Media->MediaPresent) {\r
103 DEBUG ((EFI_D_ERROR, "FileStorage: Media not present!\n"));\r
104 Status = EFI_NO_MEDIA;\r
105 goto ErrHandle;\r
106 }\r
107 if (BlkIo->Media->ReadOnly) {\r
108 DEBUG ((EFI_D_ERROR, "FileStorage: Media is read-only!\n"));\r
109 Status = EFI_ACCESS_DENIED;\r
110 goto ErrHandle;\r
111 }\r
112\r
113 Status = BlkIo->ReadBlocks(\r
114 BlkIo,\r
115 BlkIo->Media->MediaId,\r
116 0,\r
117 BLOCK_SIZE,\r
118 BootSector\r
119 );\r
120 ASSERT_EFI_ERROR (Status);\r
121 if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&\r
122 (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)\r
123 ) {\r
124 Status = EFI_NOT_FOUND;\r
125 goto ErrHandle;\r
126 }\r
127\r
128 *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));\r
129 ASSERT (*Device != NULL);\r
130\r
131ErrHandle:\r
132 return Status;\r
133}\r
134\r
135EFI_STATUS\r
136CheckStoreExists (\r
137 IN EFI_DEVICE_PATH_PROTOCOL *Device\r
138 )\r
139{\r
140 EFI_HANDLE Handle;\r
141 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
142 EFI_STATUS Status;\r
143\r
144 Status = gBS->LocateDevicePath (\r
145 &gEfiSimpleFileSystemProtocolGuid,\r
146 &Device, \r
147 &Handle\r
148 );\r
149\r
150 if (EFI_ERROR (Status)) {\r
151 return Status;\r
152 }\r
153\r
154 Status = gBS->HandleProtocol (\r
155 Handle,\r
156 &gEfiSimpleFileSystemProtocolGuid,\r
157 (VOID **) &Volume\r
158 );\r
159 if (EFI_ERROR (Status)) {\r
160 return Status;\r
161 }\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166// this routine is still running in BS period, no limitation\r
167// call FileInitStorage(), which load variable content file to memory\r
168// read the store_header, init store_header if it has not been inited (read sth. about format/heathy)\r
169// reclaim space using scratch memory\r
170\r
171VOID\r
172EFIAPI\r
173OnSimpleFileSystemInstall (\r
174 IN EFI_EVENT Event,\r
175 IN VOID *Context\r
176 )\r
177{\r
178 EFI_STATUS Status;\r
179 UINTN HandleSize;\r
180 EFI_HANDLE Handle;\r
181 EFI_DEVICE_PATH_PROTOCOL *Device;\r
182 VS_DEV *Dev;\r
183 EFI_FILE_PROTOCOL *File;\r
184 UINTN NumBytes;\r
185\r
186 Dev = (VS_DEV *) Context;\r
187 \r
188 if (VAR_FILE_DEVICEPATH (Dev) != NULL &&\r
189 !EFI_ERROR (CheckStoreExists (VAR_FILE_DEVICEPATH (Dev)))\r
190 ) {\r
191 DEBUG ((EFI_D_ERROR, "FileStorage: Already mapped!\n"));\r
192 return ;\r
193 }\r
194\r
195 while (TRUE) {\r
196 HandleSize = sizeof (EFI_HANDLE);\r
197 Status = gBS->LocateHandle (\r
198 ByRegisterNotify,\r
199 NULL,\r
200 mSFSRegistration,\r
201 &HandleSize,\r
202 &Handle\r
203 );\r
204 if (EFI_ERROR (Status)) {\r
205 return ;\r
206 }\r
207 \r
208 Status = CheckStore (Handle, VAR_FILE_VOLUMEID (Dev), &Device);\r
209 if (!EFI_ERROR (Status)) {\r
210 break;\r
211 }\r
212 }\r
213\r
214 VAR_FILE_DEVICEPATH (Dev) = Device;\r
215 Status = OpenStore (\r
216 VAR_FILE_DEVICEPATH (Dev), \r
217 VAR_FILE_FILEPATH (Dev), \r
218 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE,\r
219 &File\r
220 );\r
221 ASSERT_EFI_ERROR (Status);\r
222 \r
223 NumBytes = Dev->Size;\r
224 Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));\r
225 ASSERT_EFI_ERROR (Status);\r
226 FileClose (File);\r
227 DEBUG ((EFI_D_ERROR, "FileStorage: Mapped to file!\n"));\r
228}\r
229\r
230EFI_STATUS\r
231FileStorageConstructor (\r
232 OUT VARIABLE_STORAGE **VarStore,\r
233 OUT EFI_EVENT_NOTIFY *GoVirtualEvent,\r
234 IN EFI_PHYSICAL_ADDRESS NvStorageBase,\r
235 IN UINTN Size,\r
236 IN UINT32 VolumeId,\r
237 IN CHAR16 *FilePath\r
238 )\r
239{\r
240 VS_DEV *Dev;\r
241 EFI_STATUS Status;\r
242 EFI_EVENT Event;\r
243\r
244 Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), (VOID **) &Dev);\r
245 ASSERT_EFI_ERROR (Status);\r
246 ZeroMem (Dev, sizeof(VS_DEV));\r
247\r
248 Dev->Signature = VS_DEV_SIGNATURE;\r
249 Dev->Size = Size;\r
250 VAR_DATA_PTR (Dev) = (UINT8 *) (UINTN) NvStorageBase;\r
251 VAR_FILE_VOLUMEID (Dev) = VolumeId;\r
252 StrCpy (VAR_FILE_FILEPATH (Dev), FilePath);\r
253 Dev->VarStore.Erase = FileEraseStore;\r
254 Dev->VarStore.Write = FileWriteStore;\r
255\r
256 DEBUG ((EFI_D_ERROR, "FileStorageConstructor(0x%0x:0x%0x): added!\n", NvStorageBase, Size));\r
257\r
258 // add notify on SFS's installation.\r
259\r
260 Status = gBS->CreateEvent (\r
261 EVT_NOTIFY_SIGNAL,\r
262 TPL_CALLBACK,\r
263 OnSimpleFileSystemInstall,\r
264 Dev,\r
265 &Event\r
266 );\r
267 ASSERT_EFI_ERROR (Status);\r
268\r
269 Status = gBS->RegisterProtocolNotify (\r
270 &gEfiSimpleFileSystemProtocolGuid,\r
271 Event,\r
272 &mSFSRegistration\r
273 );\r
274 ASSERT_EFI_ERROR (Status);\r
275\r
276 *VarStore = &Dev->VarStore;\r
277 *GoVirtualEvent = OnVirtualAddressChangeFs;\r
278 return EFI_SUCCESS;\r
279}\r
280\r
281EFI_STATUS\r
282EFIAPI\r
283FileEraseStore(\r
284 IN VARIABLE_STORAGE *This\r
285 )\r
286{\r
287 EFI_STATUS Status;\r
288 VS_DEV *Dev;\r
289 EFI_FILE_PROTOCOL *File;\r
290 UINTN NumBytes;\r
291\r
292 Status = EFI_SUCCESS;\r
293 Dev = DEV_FROM_THIS(This);\r
294\r
295 SetMem (VAR_DATA_PTR (Dev), Dev->Size, VAR_DEFAULT_VALUE);\r
296\r
297 if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {\r
298 Status = OpenStore (\r
299 VAR_FILE_DEVICEPATH (Dev), \r
300 VAR_FILE_FILEPATH (Dev), \r
301 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,\r
302 &File\r
303 );\r
304 ASSERT_EFI_ERROR (Status);\r
305 NumBytes = Dev->Size;\r
306 Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));\r
307 ASSERT_EFI_ERROR (Status);\r
308 FileClose (File);\r
309 }\r
310 \r
311 return Status;\r
312}\r
313\r
314EFI_STATUS\r
315EFIAPI\r
316FileWriteStore (\r
317 IN VARIABLE_STORAGE *This,\r
318 IN UINTN Offset,\r
319 IN UINTN BufferSize,\r
320 IN VOID *Buffer\r
321 )\r
322{\r
323 EFI_STATUS Status;\r
324 VS_DEV *Dev;\r
325 EFI_FILE_PROTOCOL *File;\r
326\r
327 Status = EFI_SUCCESS;\r
328 Dev = DEV_FROM_THIS(This);\r
329\r
330 ASSERT (Buffer != NULL);\r
331 ASSERT (Offset + BufferSize <= Dev->Size);\r
332\r
333 CopyMem (VAR_DATA_PTR (Dev) + Offset, Buffer, BufferSize);\r
334 \r
335 if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {\r
336 Status = OpenStore (\r
337 VAR_FILE_DEVICEPATH (Dev), \r
338 VAR_FILE_FILEPATH (Dev), \r
339 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,\r
340 &File\r
341 );\r
342 Status = File->SetPosition (File, Offset);\r
343 ASSERT_EFI_ERROR (Status);\r
344 Status = File->Write (File, &BufferSize, Buffer);\r
345 ASSERT_EFI_ERROR (Status);\r
346 FileClose (File);\r
347 }\r
348 return Status;\r
349}\r
350\r
351VOID\r
352EFIAPI\r
353OnVirtualAddressChangeFs (\r
354 IN EFI_EVENT Event,\r
355 IN VOID *Context\r
356 )\r
357{\r
358 VS_DEV *Dev;\r
359\r
360 Dev = DEV_FROM_THIS (Context);\r
361\r
362 EfiConvertPointer (0, (VOID **) &VAR_DATA_PTR (Dev));\r
363 EfiConvertPointer (0, (VOID **) &Dev->VarStore.Erase);\r
364 EfiConvertPointer (0, (VOID **) &Dev->VarStore.Write);\r
365}\r
366\r
367EFI_STATUS\r
368OpenStore (\r
369 IN EFI_DEVICE_PATH_PROTOCOL *Device,\r
370 IN CHAR16 *FilePathName,\r
371 IN UINT64 OpenMode,\r
372 OUT EFI_FILE_PROTOCOL **File\r
373 )\r
374{\r
375 EFI_HANDLE Handle;\r
376 EFI_FILE_HANDLE Root;\r
377 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
378 EFI_STATUS Status;\r
379\r
380 *File = NULL;\r
381\r
382 Status = gBS->LocateDevicePath (\r
383 &gEfiSimpleFileSystemProtocolGuid,\r
384 &Device, \r
385 &Handle\r
386 );\r
387\r
388 if (EFI_ERROR (Status)) {\r
389 return Status;\r
390 }\r
391\r
392 Status = gBS->HandleProtocol (\r
393 Handle,\r
394 &gEfiSimpleFileSystemProtocolGuid,\r
395 (VOID **) &Volume\r
396 );\r
397 if (EFI_ERROR (Status)) {\r
398 return Status;\r
399 }\r
400\r
401 //\r
402 // Open the root directory of the volume\r
403 //\r
404 Root = NULL;\r
405 Status = Volume->OpenVolume (\r
406 Volume,\r
407 &Root\r
408 );\r
409 ASSERT_EFI_ERROR (Status);\r
410 ASSERT (Root != NULL);\r
411\r
412 //\r
413 // Open file\r
414 //\r
415 Status = Root->Open (\r
416 Root,\r
417 File,\r
418 FilePathName,\r
419 OpenMode,\r
420 0\r
421 );\r
422 if (EFI_ERROR (Status)) {\r
423 *File = NULL;\r
424 }\r
425\r
426 //\r
427 // Close the Root directory\r
428 //\r
429 Root->Close (Root);\r
430 return Status;\r
431}\r