cache.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 614 行 · 第 1/2 页
C
614 行
WorkingBufferSize = BufferSize;
PageNo = (UINTN) DriverLibDivU64x32 (Offset, Vol->CachePageSize, &UnderRun);
Length = Vol->CachePageSize - UnderRun;
Status = EFI_SUCCESS;
if (UnderRun != 0) {
//
// Offset starts in the middle of a page, so read the entire page
//
Status = FatGetCacheBuffer (Vol, PageNo, &Cache);
if (EFI_ERROR (Status)) {
goto Done;
}
if (Length > BufferSize) {
Length = BufferSize;
}
EfiCopyMem (WorkingBuffer, Cache->Data + UnderRun, Length);
if (Length == BufferSize) {
goto Done;
}
WorkingBuffer += Length;
WorkingBufferSize -= Length;
PageNo += 1;
}
OverRunPageNo = PageNo +
(UINTN) DriverLibDivU64x32 (WorkingBufferSize, Vol->CachePageSize, &OverRun);
if (WorkingBufferSize >= Vol->CachePageSize) {
//
// If the DiskIo maps directly to a BlkIo device do the read
//
if (OverRun != 0) {
WorkingBufferSize -= OverRun;
}
Status = Vol->DiskIo->ReadDisk (
Vol->DiskIo,
Vol->MediaId,
DriverLibMultU64x32 (PageNo, Vol->CachePageSize),
WorkingBufferSize,
WorkingBuffer
);
if (!Vol->Valid) {
Status = EFI_MEDIA_CHANGED;
goto Done;
}
WorkingBuffer += WorkingBufferSize;
}
if (OverRun != 0) {
//
// Last read is not a complete page
//
Status = FatGetCacheBuffer (Vol, OverRunPageNo, &Cache);
if (EFI_ERROR (Status)) {
goto Done;
}
EfiCopyMem (WorkingBuffer, Cache->Data, OverRun);
}
Done:
return Status;
}
EFI_STATUS
FatDiskIoWriteVolume (
IN FAT_VOLUME *Vol,
IN UINT64 Offset,
IN UINTN BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Write BufferSize bytes from Offset into Buffer.
Writes may require a read modify write to support writes that are not
aligned on page boundaries. There are three cases:
UnderRun - The first byte is not on a page boundary or the write request
is less than a page in length. Read modify write is required.
Aligned - A write of N contiguous pages.
OverRun - The last byte is not on a page boundary. Read modified write
required.
Arguments:
Vol - FAT file system volume.
Offset - The starting byte offset to read from.
BufferSize - Size of Buffer.
Buffer - Buffer containing read data.
Returns:
EFI_SUCCESS - The data was written correctly to the device.
EFI_WRITE_PROTECTED - The device can not be written to.
EFI_DEVICE_ERROR - The device reported an error while performing the
write.
EFI_NO_MEDIA - There is no media in the device.
EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
EFI_INVALID_PARAMETER - The write request contains device addresses that are
not valid for the device.
--*/
{
EFI_STATUS Status;
UINTN PageNo;
UINTN OverRunPageNo;
UINTN UnderRun;
UINTN OverRun;
UINTN WorkingBufferSize;
UINT8 *WorkingBuffer;
UINTN Length;
CACHE_BUFFER *Cache;
if (Vol->BlkIo->Media->ReadOnly) {
return EFI_WRITE_PROTECTED;
}
if (Vol->BlkIo->Media->MediaId != Vol->MediaId) {
return EFI_MEDIA_CHANGED;
}
if (!Vol->Valid) {
return EFI_MEDIA_CHANGED;
}
WorkingBuffer = Buffer;
WorkingBufferSize = BufferSize;
PageNo = (UINTN) DriverLibDivU64x32 (Offset, Vol->CachePageSize, &UnderRun);
Length = Vol->CachePageSize - UnderRun;
Status = EFI_SUCCESS;
if (UnderRun != 0) {
//
// Offset starts in the middle of a page,
// so read modify write to the entire page
//
Status = FatGetCacheBuffer (Vol, PageNo, &Cache);
if (EFI_ERROR (Status)) {
goto Done;
}
if (Length > BufferSize) {
Length = BufferSize;
}
EfiCopyMem (Cache->Data + UnderRun, WorkingBuffer, Length);
//
// Do not need to write to disk directly, instead, only need
// to set cache entry to dirty. Dirty cache entry will be written
// back to disk when it is flushed.
//
Cache->Dirty = TRUE;
if (Length == BufferSize) {
goto Done;
}
WorkingBuffer += Length;
WorkingBufferSize -= Length;
PageNo += 1;
}
OverRunPageNo = PageNo +
(UINTN) DriverLibDivU64x32 (WorkingBufferSize, Vol->CachePageSize, &OverRun);
if (WorkingBufferSize >= Vol->CachePageSize) {
//
// If the DiskIo maps directly to a BlkIo device do the write
//
if (OverRun != 0) {
WorkingBufferSize -= OverRun;
}
Status = Vol->DiskIo->WriteDisk (
Vol->DiskIo,
Vol->MediaId,
DriverLibMultU64x32 (PageNo, Vol->CachePageSize),
WorkingBufferSize,
WorkingBuffer
);
if (!Vol->Valid) {
Status = EFI_MEDIA_CHANGED;
goto Done;
}
WorkingBuffer += WorkingBufferSize;
//
// If this write over laps a read buffer it must be flushed
//
FatCacheFlushRange (Vol, PageNo, OverRunPageNo);
}
if (OverRun != 0) {
//
// Last bit is not a complete block, so do a read modify write
//
Status = FatGetCacheBuffer (Vol, OverRunPageNo, &Cache);
if (EFI_ERROR (Status)) {
goto Done;
}
EfiCopyMem (Cache->Data, WorkingBuffer, OverRun);
//
// Do not need to write to disk directly, instead, only need
// to set cache entry to dirty. Dirty cache entry will be written
// back to disk when it is flushed.
//
Cache->Dirty = TRUE;
}
Done:
return Status;
}
EFI_STATUS
FatVolumeFlushCache (
IN FAT_VOLUME *Vol
)
/*++
Routine Description:
Arguments:
Vol - FAT file system volume.
Returns:
EFI_STATUS
--*/
{
EFI_STATUS Status;
UINTN Index;
EFI_TPL EntryTpl;
Status = EFI_SUCCESS;
if (Vol->Valid == FALSE) {
return EFI_MEDIA_CHANGED;
}
//
// Make Cache Update a critical section
//
EntryTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
for (Index = 0; Index < FAT_CACHE_SIZE; Index++) {
if (Vol->Cache[Index].Valid == TRUE) {
if (Vol->Cache[Index].Dirty == TRUE) {
//
// Write back all Dirty cache entries to disk
//
Status = Vol->DiskIo->WriteDisk (
Vol->DiskIo,
Vol->MediaId,
DriverLibMultU64x32 (Vol->Cache[Index].PageNo, Vol->CachePageSize),
Vol->CachePageSize,
Vol->Cache[Index].Data
);
if (EFI_ERROR (Status)) {
Vol->Cache[Index].Valid = FALSE;
gBS->RestoreTPL (EntryTpl);
return Status;
}
Vol->Cache[Index].Dirty = FALSE;
}
}
}
//
// Exit Cache Update critical section
//
gBS->RestoreTPL (EntryTpl);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?