]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/FSVariable/FileStorage.c
Update the copyright notice format
[mirror_edk2.git] / DuetPkg / FSVariable / FileStorage.c
CommitLineData
9071550e 1/*++\r
2\r
b1f700a8
HT
3Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
9071550e 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
9071550e 31VOID\r
32EFIAPI\r
e56dd2ce 33OnVirtualAddressChangeFs (\r
9071550e 34 IN EFI_EVENT Event,\r
35 IN VOID *Context\r
36 );\r
37\r
9071550e 38EFI_STATUS\r
39EFIAPI\r
40FileEraseStore(\r
41 IN VARIABLE_STORAGE *This\r
42 );\r
43\r
9071550e 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
9071550e 53EFI_STATUS\r
54OpenStore (\r
55 IN EFI_DEVICE_PATH_PROTOCOL *Device,\r
56 IN CHAR16 *FilePathName,\r
57 IN UINT64 OpenMode,\r
b0b961c8 58 OUT EFI_FILE_PROTOCOL **File\r
9071550e 59 );\r
60\r
61//\r
62// Implementation below:\r
63//\r
9071550e 64VOID\r
65FileClose (\r
b0b961c8 66 IN EFI_FILE_PROTOCOL *File\r
9071550e 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
7c04a679 157 (VOID **) &Volume\r
9071550e 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
9071550e 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
b0b961c8 183 EFI_FILE_PROTOCOL *File;\r
9071550e 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
571f4f52 226 FileClose (File);\r
9071550e 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
7c04a679 244 Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), (VOID **) &Dev);\r
9071550e 245 ASSERT_EFI_ERROR (Status);\r
246 ZeroMem (Dev, sizeof(VS_DEV));\r
247\r
439c34f3 248 Dev->Signature = VS_DEV_SIGNATURE;\r
9071550e 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
e53a6ea9 261 EVT_NOTIFY_SIGNAL,\r
9071550e 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
e56dd2ce 277 *GoVirtualEvent = OnVirtualAddressChangeFs;\r
9071550e 278 return EFI_SUCCESS;\r
279}\r
280\r
9071550e 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
b0b961c8 289 EFI_FILE_PROTOCOL *File;\r
9071550e 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
9071550e 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
b0b961c8 325 EFI_FILE_PROTOCOL *File;\r
9071550e 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
9071550e 351VOID\r
352EFIAPI\r
e56dd2ce 353OnVirtualAddressChangeFs (\r
9071550e 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
7c04a679 362 EfiConvertPointer (0, (VOID **) &VAR_DATA_PTR (Dev));\r
9071550e 363 EfiConvertPointer (0, (VOID **) &Dev->VarStore.Erase);\r
364 EfiConvertPointer (0, (VOID **) &Dev->VarStore.Write);\r
365}\r
366\r
9071550e 367EFI_STATUS\r
368OpenStore (\r
369 IN EFI_DEVICE_PATH_PROTOCOL *Device,\r
370 IN CHAR16 *FilePathName,\r
371 IN UINT64 OpenMode,\r
b0b961c8 372 OUT EFI_FILE_PROTOCOL **File\r
9071550e 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
7c04a679 395 (VOID **) &Volume\r
9071550e 396 );\r
397 if (EFI_ERROR (Status)) {\r
398 return Status;\r
399 }\r
be768885 400\r
9071550e 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