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