|
本帖最后由 sunsea 于 2020-11-6 17:10 编辑
阅读了一下SVBus处理INT13信息的关键代码
- // we do two RAM mappings, because if we would map the first MB of physical memory we get the following problems:
- // - on Windows 10 x64 Build 1709 we get the bug check 0x1A MEMORY_MANAGEMENT if WinDbg is attached and the driver runs on an ESXi machine
- // - on Windows 10 x64 Build 1803 MmMapIoSpace returns NULL for the virtual address even without an attached debugger on an ESXi machine
- // map real mode RAM range 0 - 1024 bytes
- physAddr.QuadPart = 0;
- mapSize = 0x400;
- // map physical address range to nonpaged system space
- // we should map this non cached, otherwise Driver Verifier shows the following error in WinDbg: Iospace mapping overlap
- // the reason is because the OS has already mapped the same address range with another cache type
- virtAddr = (PUCHAR)MmMapIoSpace(physAddr,mapSize,MmNonCached);
- if(virtAddr == NULL)
- {
- IoDeleteSymbolicLink(&DosDeviceName);
- IoDetachDevice(DeviceExtension->Bus.LowerDeviceObject);
- IoDeleteDevice(DeviceObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- // get interrupt vector for int13h
- intVector = ((INTERRUPT_VECTOR*)(VOID*)(virtAddr))[0x13];
-
- // unmap real mode RAM range 0 - 1024 bytes
- MmUnmapIoSpace(virtAddr,mapSize);
- // map real mode RAM INT13 segment for a size of interrupt vector offset + 1024 bytes
- physAddr.QuadPart = (LONGLONG)intVector.Segment << 4;
- mapSize = (SIZE_T)intVector.Offset + 0x400;
- // map physical address range to nonpaged system space
- // we should map this non cached, otherwise Driver Verifier shows the following error in WinDbg: Iospace mapping overlap
- // the reason is because the OS has already mapped the same address range with another cache type
- virtAddr = (PUCHAR)MmMapIoSpace(physAddr,mapSize,MmNonCached);
- if(virtAddr == NULL)
- {
- IoDeleteSymbolicLink(&DosDeviceName);
- IoDetachDevice(DeviceExtension->Bus.LowerDeviceObject);
- IoDeleteDevice(DeviceObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- // check for the GRUB4DOS identify string "$INT13SFGRUB4DOS" at int13h offset + 0x03
- if(RtlCompareMemory(&virtAddr[intVector.Offset + 0x03],"$INT13SFGRUB4DOS",(SIZE_T)0x10) == 0x10)
- {
- // GRUB4DOS identify string "$INT13SFGRUB4DOS" found
-
- // copy all GRUB4DOS drive map slots to our driver context area slot structure
- RtlCopyMemory(&DriverExtension->slot[0],&virtAddr[0x20],sizeof(GRUB4DOS_DRIVE_MAP_SLOT) * MAXIMUM_GRUB4DOS_DRIVE_MAP_SLOTS);
- // unmap real mode RAM INT13 segment for a size of interrupt vector offset + 1024 bytes
- MmUnmapIoSpace(virtAddr,mapSize);
- return STATUS_SUCCESS;
- }
- // unmap real mode RAM INT13 segment for a size of interrupt vector offset + 1024 bytes
- MmUnmapIoSpace(virtAddr,mapSize);
- // GRUB4DOS identify string "$INT13SFGRUB4DOS" not found
- // we now try to search for the GRUB4DOS INT13 handler in the first 640 KB
- // check the first 640 KB for the GRUB4DOS identify string "$INT13SFGRUB4DOS"
- // we search in reverse order from top to down, because this is faster
- for(i = 0x9F000; i >= 0; i -= 0x1000)
- {
- // map real mode RAM address for a size of 4096 bytes
- physAddr.QuadPart = (LONGLONG)i;
- mapSize = 0x1000;
- // map physical address range to nonpaged system space
- // we should map this non cached, otherwise Driver Verifier shows the following error in WinDbg: Iospace mapping overlap
- // the reason is because the OS has already mapped the same address range with another cache type
- virtAddr = (PUCHAR)MmMapIoSpace(physAddr,mapSize,MmNonCached);
- if(virtAddr == NULL)
- {
- IoDeleteSymbolicLink(&DosDeviceName);
- IoDetachDevice(DeviceExtension->Bus.LowerDeviceObject);
- IoDeleteDevice(DeviceObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- // do this for 4096 bytes - 16 bytes for the GRUB4DOS identify string "$INT13SFGRUB4DOS"
- for(k = 0; k < 0xFF0; k++)
- {
- // check for the GRUB4DOS identify string "$INT13SFGRUB4DOS"
- if(RtlCompareMemory(&virtAddr[k],"$INT13SFGRUB4DOS",(SIZE_T)0x10) == 0x10)
- {
- // GRUB4DOS identify string "$INT13SFGRUB4DOS" found
-
- // copy all GRUB4DOS drive map slots to our driver context area slot structure
- // k - 0xE3 is the start offset of our drive map table, this negative memory range is included in our memory map
- RtlCopyMemory(&DriverExtension->slot[0],&virtAddr[k - 0xE3],sizeof(GRUB4DOS_DRIVE_MAP_SLOT) * MAXIMUM_GRUB4DOS_DRIVE_MAP_SLOTS);
- // unmap real mode RAM address for a size of 4096 bytes
- MmUnmapIoSpace(virtAddr,mapSize);
- return STATUS_SUCCESS;
- }
- }
- // unmap real mode RAM address for a size of 4096 bytes
- MmUnmapIoSpace(virtAddr,mapSize);
- }
复制代码
可以发现是直接套用了G4D对于映射信息的格式:
- /*lint -esym(768,_GRUB4DOS_DRIVE_MAP_SLOT::in_situ) Info 768: global struct member not referenced */
- typedef struct _GRUB4DOS_DRIVE_MAP_SLOT
- {
- UCHAR from_drive;
- UCHAR to_drive; // 0xFF indicates a memdrive
- UCHAR max_head;
- UCHAR max_sector:6;
- UCHAR disable_lba:1; // bit 6: disable lba
- UCHAR read_only:1; // bit 7: read only
- USHORT to_cylinder:13; // max cylinder of the TO drive
- USHORT from_cdrom:1; // bit 13: FROM drive is CDROM(with big 2048-byte sector)
- USHORT to_cdrom:1; // bit 14: TO drive is CDROM(with big 2048-byte sector)
- USHORT to_support_lba:1; // bit 15: TO drive support LBA
- UCHAR to_head; // max head of the TO drive
- UCHAR to_sector:6; // max sector of the TO drive
- UCHAR fake_write:1; // bit 6: fake-write or safe-boot
- UCHAR in_situ:1; // bit 7: in-situ
- ULONGLONG start_sector;
- ULONGLONG sector_count;
- }GRUB4DOS_DRIVE_MAP_SLOT,*PGRUB4DOS_DRIVE_MAP_SLOT;
复制代码
重点句:
- // copy all GRUB4DOS drive map slots to our driver context area slot structure
- // k - 0xE3 is the start offset of our drive map table, this negative memory range is included in our memory map
- RtlCopyMemory(&DriverExtension->slot[0],&virtAddr[k - 0xE3],sizeof(GRUB4DOS_DRIVE_MAP_SLOT) * MAXIMUM_GRUB4DOS_DRIVE_MAP_SLOTS);
复制代码
直接拷贝,毫无改写!
再看一下对于内存映射的处理也是直来直去型的。
那么请问yaya,可不可以设计一个UEFI变量,名字就叫$INT13SFGRUB4DOS之类,然后内部存储的信息还是上面这个GRUB4DOS_DRIVE_MAP_SLOT结构?大概这样问题就能解决了。
只要命名空间的GUID明确而且有EFI_VARIABLE_RUNTIME_ACCESS 这个属性应该都可以读到,我是觉得可能map的时候设置一下EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS。
|
|