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
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.
18 handles variable store/reads on file
23 #include "FSVariable.h"
25 VOID
*mSFSRegistration
;
34 OnVirtualAddressChange (
43 IN VARIABLE_STORAGE
*This
50 IN VARIABLE_STORAGE
*This
,
59 IN EFI_DEVICE_PATH_PROTOCOL
*Device
,
60 IN CHAR16
*FilePathName
,
66 // Implementation below:
76 Status
= File
->Flush (File
);
77 ASSERT_EFI_ERROR (Status
);
79 Status
= File
->Close (File
);
80 ASSERT_EFI_ERROR (Status
);
85 IN EFI_HANDLE SimpleFileSystemHandle
,
87 OUT EFI_DEVICE_PATH_PROTOCOL
**Device
90 #define BLOCK_SIZE 0x200
91 #define FAT16_VOLUME_ID_OFFSET 39
92 #define FAT32_VOLUME_ID_OFFSET 67
94 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
95 UINT8 BootSector
[BLOCK_SIZE
];
98 Status
= gBS
->HandleProtocol (
99 SimpleFileSystemHandle
,
100 &gEfiBlockIoProtocolGuid
, // BlockIo should be supported if it supports SimpleFileSystem
104 if (EFI_ERROR (Status
)) {
107 if (!BlkIo
->Media
->MediaPresent
) {
108 DEBUG ((EFI_D_ERROR
, "FileStorage: Media not present!\n"));
109 Status
= EFI_NO_MEDIA
;
112 if (BlkIo
->Media
->ReadOnly
) {
113 DEBUG ((EFI_D_ERROR
, "FileStorage: Media is read-only!\n"));
114 Status
= EFI_ACCESS_DENIED
;
118 Status
= BlkIo
->ReadBlocks(
120 BlkIo
->Media
->MediaId
,
125 ASSERT_EFI_ERROR (Status
);
126 if ((*(UINT32
*) &BootSector
[FAT16_VOLUME_ID_OFFSET
] != VolumeId
) &&
127 (*(UINT32
*) &BootSector
[FAT32_VOLUME_ID_OFFSET
] != VolumeId
)
129 Status
= EFI_NOT_FOUND
;
133 *Device
= DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle
));
134 ASSERT (*Device
!= NULL
);
142 IN EFI_DEVICE_PATH_PROTOCOL
*Device
146 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
149 Status
= gBS
->LocateDevicePath (
150 &gEfiSimpleFileSystemProtocolGuid
,
155 if (EFI_ERROR (Status
)) {
159 Status
= gBS
->HandleProtocol (
161 &gEfiSimpleFileSystemProtocolGuid
,
164 if (EFI_ERROR (Status
)) {
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
179 OnSimpleFileSystemInstall (
187 EFI_DEVICE_PATH_PROTOCOL
*Device
;
192 Dev
= (VS_DEV
*) Context
;
194 if (VAR_FILE_DEVICEPATH (Dev
) != NULL
&&
195 !EFI_ERROR (CheckStoreExists (VAR_FILE_DEVICEPATH (Dev
)))
197 DEBUG ((EFI_D_ERROR
, "FileStorage: Already mapped!\n"));
202 HandleSize
= sizeof (EFI_HANDLE
);
203 Status
= gBS
->LocateHandle (
210 if (EFI_ERROR (Status
)) {
214 Status
= CheckStore (Handle
, VAR_FILE_VOLUMEID (Dev
), &Device
);
215 if (!EFI_ERROR (Status
)) {
220 VAR_FILE_DEVICEPATH (Dev
) = Device
;
222 VAR_FILE_DEVICEPATH (Dev
),
223 VAR_FILE_FILEPATH (Dev
),
224 EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_CREATE
,
227 ASSERT_EFI_ERROR (Status
);
229 NumBytes
= Dev
->Size
;
230 Status
= File
->Write (File
, &NumBytes
, VAR_DATA_PTR (Dev
));
231 ASSERT_EFI_ERROR (Status
);
232 // KEN: bugbug here if closing file, volume handle will be free,
233 // and system will be hang when accessing volume handle in future.
235 DEBUG ((EFI_D_ERROR
, "FileStorage: Mapped to file!\n"));
239 FileStorageConstructor (
240 OUT VARIABLE_STORAGE
**VarStore
,
241 OUT EFI_EVENT_NOTIFY
*GoVirtualEvent
,
242 IN EFI_PHYSICAL_ADDRESS NvStorageBase
,
252 Status
= gBS
->AllocatePool (EfiRuntimeServicesData
, sizeof(VS_DEV
), &Dev
);
253 ASSERT_EFI_ERROR (Status
);
254 ZeroMem (Dev
, sizeof(VS_DEV
));
256 Dev
->Signature
= VARIABLE_STORE_SIGNATURE
;
258 VAR_DATA_PTR (Dev
) = (UINT8
*) (UINTN
) NvStorageBase
;
259 VAR_FILE_VOLUMEID (Dev
) = VolumeId
;
260 StrCpy (VAR_FILE_FILEPATH (Dev
), FilePath
);
261 Dev
->VarStore
.Erase
= FileEraseStore
;
262 Dev
->VarStore
.Write
= FileWriteStore
;
264 DEBUG ((EFI_D_ERROR
, "FileStorageConstructor(0x%0x:0x%0x): added!\n", NvStorageBase
, Size
));
266 // add notify on SFS's installation.
268 Status
= gBS
->CreateEvent (
271 OnSimpleFileSystemInstall
,
275 ASSERT_EFI_ERROR (Status
);
277 Status
= gBS
->RegisterProtocolNotify (
278 &gEfiSimpleFileSystemProtocolGuid
,
282 ASSERT_EFI_ERROR (Status
);
284 *VarStore
= &Dev
->VarStore
;
285 *GoVirtualEvent
= OnVirtualAddressChange
;
293 IN VARIABLE_STORAGE
*This
301 Status
= EFI_SUCCESS
;
302 Dev
= DEV_FROM_THIS(This
);
304 SetMem (VAR_DATA_PTR (Dev
), Dev
->Size
, VAR_DEFAULT_VALUE
);
306 if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev
) != NULL
) {
308 VAR_FILE_DEVICEPATH (Dev
),
309 VAR_FILE_FILEPATH (Dev
),
310 EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_READ
,
313 ASSERT_EFI_ERROR (Status
);
314 NumBytes
= Dev
->Size
;
315 Status
= File
->Write (File
, &NumBytes
, VAR_DATA_PTR (Dev
));
316 ASSERT_EFI_ERROR (Status
);
327 IN VARIABLE_STORAGE
*This
,
337 Status
= EFI_SUCCESS
;
338 Dev
= DEV_FROM_THIS(This
);
340 ASSERT (Buffer
!= NULL
);
341 ASSERT (Offset
+ BufferSize
<= Dev
->Size
);
343 CopyMem (VAR_DATA_PTR (Dev
) + Offset
, Buffer
, BufferSize
);
345 if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev
) != NULL
) {
347 VAR_FILE_DEVICEPATH (Dev
),
348 VAR_FILE_FILEPATH (Dev
),
349 EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_READ
,
352 Status
= File
->SetPosition (File
, Offset
);
353 ASSERT_EFI_ERROR (Status
);
354 Status
= File
->Write (File
, &BufferSize
, Buffer
);
355 ASSERT_EFI_ERROR (Status
);
364 OnVirtualAddressChange (
371 Dev
= DEV_FROM_THIS (Context
);
373 EfiConvertPointer (0, &VAR_DATA_PTR (Dev
));
374 EfiConvertPointer (0, (VOID
**) &Dev
->VarStore
.Erase
);
375 EfiConvertPointer (0, (VOID
**) &Dev
->VarStore
.Write
);
381 IN EFI_DEVICE_PATH_PROTOCOL
*Device
,
382 IN CHAR16
*FilePathName
,
388 EFI_FILE_HANDLE Root
;
389 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
394 Status
= gBS
->LocateDevicePath (
395 &gEfiSimpleFileSystemProtocolGuid
,
400 if (EFI_ERROR (Status
)) {
404 Status
= gBS
->HandleProtocol (
406 &gEfiSimpleFileSystemProtocolGuid
,
409 if (EFI_ERROR (Status
)) {
414 // Open the root directory of the volume
417 Status
= Volume
->OpenVolume (
421 ASSERT_EFI_ERROR (Status
);
422 ASSERT (Root
!= NULL
);
427 Status
= Root
->Open (
434 if (EFI_ERROR (Status
)) {
439 // Close the Root directory