ROM镜像的备份与还原
实现Setup下面BIOS的备份还原
该功能实现两个方面,备份到U盘、从U盘还原
1、备份到U盘
把rom里的数据复制到盘中
1)找到FAT32的文件系统
每个UEFI系统至少有一个ESP(EFI System Partition)分区,在这个分区上存放了启动文件。既然操作系统加载器以文件的形式存放在ESP分区内,UEFI就需要有读写文件的功能。
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&HandleCount,
&FileSystemHandles
);
2) 通过EFI_SIMPLE_FILE_SYSYTEM_PROTOCOL中的OpenVolume,可以获得FAT文件系统上的根目录句柄,目录句柄(EFI_FILE_PROTOCOL)包含了操作该目录里文件的文件操作接口。
struct _EFI_FILE_PROTOCOL {
///
/// The version of the EFI_FILE_PROTOCOL interface. The version specified
/// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION.
/// Future versions are required to be backward compatible to version 1.0.
///
UINT64 Revision;
EFI_FILE_OPEN Open;
EFI_FILE_CLOSE Close;
EFI_FILE_DELETE Delete;
EFI_FILE_READ Read;
EFI_FILE_WRITE Write;
EFI_FILE_GET_POSITION GetPosition;
EFI_FILE_SET_POSITION SetPosition;
EFI_FILE_GET_INFO GetInfo;
EFI_FILE_SET_INFO SetInfo;
EFI_FILE_FLUSH Flush;
EFI_FILE_OPEN_EX OpenEx;
EFI_FILE_READ_EX ReadEx;
EFI_FILE_WRITE_EX WriteEx;
EFI_FILE_FLUSH_EX FlushEx;
};
文件打开方式
| 文件打开模式 | 用途 |
|---|---|
| EFI_FILE_MODE_READ | 文件用于读 |
| :EFI_FILE_MODE_WRITE | 文件用于写 |
| EFI_FILE_MODE_CREATE | 若文件不存在,则创建: |
3)使用SpiFlashRead读BIOS中的数据,再用EFI_FILE_PROTOCOL->Write写到文件中
写文件
FileIo的Write函数
typedef EFI_STATUS (EFIAPI *EFI_FILE_WRITE)( IN EFI_FILE_PROTOCOL *This, //文件句柄 IN OUT UINTN *BufferSize, //输入:要写入的数据长度;输出:实际写入的数据长度 IN VOID *Buffer //待写入数据 );
Write 只能写数据到文件,不能写数据到目录。通过,Write函数会写BufferSize指定的字节数到文件中(实际写的字节数等于指定要写的字节数),仅在遇到错误时(例如,卷上没有多余空间时)会写部分数据到文件,此时bufferSize返回实际写的字节数。
4)使用gEfiSimpleFileSystemProtocolGuid寻找FAT32 分区,如果U盘或者硬盘没有该分区,也无法备份
2、从U盘恢复镜像
从盘中读数据写到rom上
1)找到FAT32的文件系统
每个UEFI系统至少有一个ESP(EFI System Partition)分区,在这个分区上存放了启动文件。既然操作系统加载器以文件的形式存放在ESP分区内,UEFI就需要有读写文件的功能。
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&HandleCount,
&FileSystemHandles
);
2) 通过EFI_SIMPLE_FILE_SYSYTEM_PROTOCOL中的OpenVolume,可以获得FAT文件系统上的根目录句柄,目录句柄(EFI_FILE_PROTOCOL)包含了操作该目录里文件的文件操作接口。
struct _EFI_FILE_PROTOCOL {
///
/// The version of the EFI_FILE_PROTOCOL interface. The version specified
/// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION.
/// Future versions are required to be backward compatible to version 1.0.
///
UINT64 Revision;
EFI_FILE_OPEN Open;
EFI_FILE_CLOSE Close;
EFI_FILE_DELETE Delete;
EFI_FILE_READ Read;
EFI_FILE_WRITE Write;
EFI_FILE_GET_POSITION GetPosition;
EFI_FILE_SET_POSITION SetPosition;
EFI_FILE_GET_INFO GetInfo;
EFI_FILE_SET_INFO SetInfo;
EFI_FILE_FLUSH Flush;
EFI_FILE_OPEN_EX OpenEx;
EFI_FILE_READ_EX ReadEx;
EFI_FILE_WRITE_EX WriteEx;
EFI_FILE_FLUSH_EX FlushEx;
};
3)SPI 接口可以用于连接 FLASH 芯片
struct _EFI_SPI_PROTOCOL {
EFI_SPI_INIT Init;
EFI_SPI_LOCK Lock;
EFI_SPI_ERASE Erase;
EFI_SPI_PROGRAM Program;
EFI_SPI_READ Read;
EFI_SPI_EXECUTE Execute;
EFI_SPI_GET_INFO GetInfo;
};
使用 SpiFlashRead 读BIOS中的数据,
使用 SpiFlashBlockErase 擦掉BIOS中的数据,
使用 SpiFlashWrite 把文件数据写入rom里
3、设备区分
如果多个FAT文件块,怎么区分备份到U盘还是SATA盘
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&HandleCount,
&FileSystemHandles
);
for (Index = 0; Index < HandleCount; Index++){
Status = gBS->HandleProtocol (
FileSystemHandles[Index],
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
USB:BlkIo->Media->RemovableMedia = 1
SATA:BlkIo->Media->RemovableMedia = 0