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