无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站广告联系 微信:wuyouceo QQ:184822951
查看: 385807|回复: 3276
打印 上一主题 下一主题

[原创] GRUB4DOS for UEFI

    [复制链接]
1#
发表于 2020-11-2 21:28:25 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-2 21:40 编辑
wintoflash 发表于 2020-11-2 19:18
试了一下,通过UEFI环境变量传递内存盘地址是可行的。
如图,我写了个小程序,在windows下获取grub2创建 ...

以前稍微搞过这种东西……
其实不仅是驱动的问题,重要的是如何让系统在第一轮驱动加载之前,让【bootmgfw.efi】正确的把【bcd】,【winload.efi】,【SYSTEM】读进内存。这是最麻烦的。

bootmgr时代,bootmgr是直接呼叫INT13来读第一轮的这些东西,然后由ntoskrnl.exe加载磁盘驱动,才切换进用磁盘驱动度盘。

现在不知道bootmgfw.efi怎么操作。可能需要调试确定。这一步搞定后面就比较好办了。

怀疑bootmgfw.efi可能调用了UEFI BIOS的相关功能。需要有技术的同志帮忙确定。

回复

使用道具 举报

2#
发表于 2020-11-3 11:54:59 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-3 11:56 编辑
wintoflash 发表于 2020-11-2 21:57
这是最不麻烦的。
GRUB2 UEFI 的 map, wimboot, ntboot,GRUB4DOS BIOS 和 UEFI 下的 map, Syslinux ...

如果已经UEFI下做到了,那就非常好,我们只需要接着搞磁盘驱动那一层了——我觉得修改SVBus使其能够从UEFI环境变量或者其他什么可靠参数传递渠道读地址的方案成功概率是最大的。

确实大概我对这些技术进展落后了。

BIOS下grub4dos的map起效,是因为g4d接管了int13,所以bootmgr能顺利读盘。如果现在在UEFI环境下对bootmgfw.efi的仿真措施已经成熟,那就非常给力了。

胜利有望了……毕竟磁盘驱动这一层微软好歹已经有文档化的东西和接口,bootmgr/bootmgfw.efi这一层简直是摸黑操作。

这几天找找资料看看能不能hack一下SVBus之类的玩意……

回复

使用道具 举报

3#
发表于 2020-11-3 13:55:23 来自手机 | 显示全部楼层
chenall 发表于 2020-11-3 12:52
印象中imdisk
好像有一个功能可以映射指定内存地址区域作为磁盘的。



目前只要确定bootmgfw.efi能够正确从g4d uefi中map的磁盘里正确读取bcd,SYSTEM等几个文件,那么剩下的事情非常简单,但是考虑到map还分非mem和mem,那么imdisk可能会比较麻烦,还是SVBus比较好,只需要hack一下获取map信息的方式就好了……

签名问题应该可以通过bcd设置解决。
回复

使用道具 举报

4#
发表于 2020-11-3 14:11:04 来自手机 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-3 14:14 编辑
liuzhaoyzz 发表于 2020-11-3 14:05
SVbus是开源的,如果你能够修改直接修改源代码,编译即可,不需要hack吧。




说的就是直接改源码。有时间我去看看M$有没有在核心模式下读UEFI环境变量的。然后请yaya设计一下信息传递格式。

非常好,M$有现成的API,ExGetFirmwareEnvironmentVariable,有时间我去试着改SVBus之类的驱动吧。
回复

使用道具 举报

5#
发表于 2020-11-3 14:16:27 来自手机 | 显示全部楼层
liuzhaoyzz 发表于 2020-11-3 14:15
答主厉害啊!静候佳音了!

过奖了过奖了,目前我还不知道bootmgfw.efi那头彻底搞定了没有,希望如此。
回复

使用道具 举报

6#
发表于 2020-11-3 14:21:00 来自手机 | 显示全部楼层
liuzhaoyzz 发表于 2020-11-3 14:15
答主厉害啊!静候佳音了!

有个小小的问题,ExGetFirmwareEnvironmentVariable这个核心API只在Win8和以后有,也就意味着win7不受支持。不过这应该不是个大问题吧?
回复

使用道具 举报

7#
发表于 2020-11-6 15:48:58 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-6 15:51 编辑

做个了个小测试,在2016 LTSB的内核环境里成功读到了UEFI变量。
读了一下PlatformLangCodes这个UEFI Spec中规定的Globally Defined Variables。

只要命名空间的GUID明确而且有EFI_VARIABLE_RUNTIME_ACCESS 这个属性应该都可以读到,我是觉得可能map的时候设置一下EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,这两个属性都要比较好。
下一步就是看看SVBus处理磁盘映射的时候读了什么信息然后做针对性修改了。


回复

使用道具 举报

8#
发表于 2020-11-6 17:07:32 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-6 17:10 编辑

阅读了一下SVBus处理INT13信息的关键代码

  1.         // we do two RAM mappings, because if we would map the first MB of physical memory we get the following problems:
  2.         // - 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
  3.         // - on Windows 10 x64 Build 1803 MmMapIoSpace returns NULL for the virtual address even without an attached debugger on an ESXi machine
  4.         // map real mode RAM range 0 - 1024 bytes
  5.         physAddr.QuadPart = 0;
  6.         mapSize = 0x400;
  7.         // map physical address range to nonpaged system space
  8.         // we should map this non cached, otherwise Driver Verifier shows the following error in WinDbg: Iospace mapping overlap
  9.         // the reason is because the OS has already mapped the same address range with another cache type
  10.         virtAddr = (PUCHAR)MmMapIoSpace(physAddr,mapSize,MmNonCached);
  11.         if(virtAddr == NULL)
  12.         {
  13.                 IoDeleteSymbolicLink(&DosDeviceName);
  14.                 IoDetachDevice(DeviceExtension->Bus.LowerDeviceObject);
  15.                 IoDeleteDevice(DeviceObject);
  16.                 return STATUS_INSUFFICIENT_RESOURCES;                        
  17.         }

  18.         // get interrupt vector for int13h
  19.         intVector = ((INTERRUPT_VECTOR*)(VOID*)(virtAddr))[0x13];
  20.         
  21.         // unmap real mode RAM range 0 - 1024 bytes
  22.         MmUnmapIoSpace(virtAddr,mapSize);

  23.         // map real mode RAM INT13 segment for a size of interrupt vector offset + 1024 bytes
  24.         physAddr.QuadPart = (LONGLONG)intVector.Segment << 4;
  25.         mapSize = (SIZE_T)intVector.Offset + 0x400;
  26.         // map physical address range to nonpaged system space
  27.         // we should map this non cached, otherwise Driver Verifier shows the following error in WinDbg: Iospace mapping overlap
  28.         // the reason is because the OS has already mapped the same address range with another cache type
  29.         virtAddr = (PUCHAR)MmMapIoSpace(physAddr,mapSize,MmNonCached);
  30.         if(virtAddr == NULL)
  31.         {
  32.                 IoDeleteSymbolicLink(&DosDeviceName);
  33.                 IoDetachDevice(DeviceExtension->Bus.LowerDeviceObject);
  34.                 IoDeleteDevice(DeviceObject);
  35.                 return STATUS_INSUFFICIENT_RESOURCES;                        
  36.         }

  37.         // check for the GRUB4DOS identify string "$INT13SFGRUB4DOS" at int13h offset + 0x03
  38.         if(RtlCompareMemory(&virtAddr[intVector.Offset + 0x03],"$INT13SFGRUB4DOS",(SIZE_T)0x10) == 0x10)
  39.         {
  40.                 // GRUB4DOS identify string "$INT13SFGRUB4DOS" found
  41.                
  42.                 // copy all GRUB4DOS drive map slots to our driver context area slot structure
  43.                 RtlCopyMemory(&DriverExtension->slot[0],&virtAddr[0x20],sizeof(GRUB4DOS_DRIVE_MAP_SLOT) * MAXIMUM_GRUB4DOS_DRIVE_MAP_SLOTS);

  44.                 // unmap real mode RAM INT13 segment for a size of interrupt vector offset + 1024 bytes
  45.                 MmUnmapIoSpace(virtAddr,mapSize);

  46.                 return STATUS_SUCCESS;
  47.         }

  48.         // unmap real mode RAM INT13 segment for a size of interrupt vector offset + 1024 bytes
  49.         MmUnmapIoSpace(virtAddr,mapSize);

  50.         // GRUB4DOS identify string "$INT13SFGRUB4DOS" not found
  51.         // we now try to search for the GRUB4DOS INT13 handler in the first 640 KB

  52.         // check the first 640 KB for the GRUB4DOS identify string "$INT13SFGRUB4DOS"
  53.         // we search in reverse order from top to down, because this is faster
  54.         for(i = 0x9F000; i >= 0; i -= 0x1000)
  55.         {
  56.                 // map real mode RAM address for a size of 4096 bytes
  57.                 physAddr.QuadPart = (LONGLONG)i;
  58.                 mapSize = 0x1000;
  59.                 // map physical address range to nonpaged system space
  60.                 // we should map this non cached, otherwise Driver Verifier shows the following error in WinDbg: Iospace mapping overlap
  61.                 // the reason is because the OS has already mapped the same address range with another cache type
  62.                 virtAddr = (PUCHAR)MmMapIoSpace(physAddr,mapSize,MmNonCached);
  63.                 if(virtAddr == NULL)
  64.                 {
  65.                         IoDeleteSymbolicLink(&DosDeviceName);
  66.                         IoDetachDevice(DeviceExtension->Bus.LowerDeviceObject);
  67.                         IoDeleteDevice(DeviceObject);
  68.                         return STATUS_INSUFFICIENT_RESOURCES;                        
  69.                 }

  70.                 // do this for 4096 bytes - 16 bytes for the GRUB4DOS identify string "$INT13SFGRUB4DOS"
  71.                 for(k = 0; k < 0xFF0; k++)
  72.                 {
  73.                         // check for the GRUB4DOS identify string "$INT13SFGRUB4DOS"
  74.                         if(RtlCompareMemory(&virtAddr[k],"$INT13SFGRUB4DOS",(SIZE_T)0x10) == 0x10)
  75.                         {
  76.                                 // GRUB4DOS identify string "$INT13SFGRUB4DOS" found
  77.                
  78.                                 // copy all GRUB4DOS drive map slots to our driver context area slot structure
  79.                                 // k - 0xE3 is the start offset of our drive map table, this negative memory range is included in our memory map
  80.                                 RtlCopyMemory(&DriverExtension->slot[0],&virtAddr[k - 0xE3],sizeof(GRUB4DOS_DRIVE_MAP_SLOT) * MAXIMUM_GRUB4DOS_DRIVE_MAP_SLOTS);

  81.                                 // unmap real mode RAM address for a size of 4096 bytes
  82.                                 MmUnmapIoSpace(virtAddr,mapSize);

  83.                                 return STATUS_SUCCESS;
  84.                         }
  85.                 }

  86.                 // unmap real mode RAM address for a size of 4096 bytes
  87.                 MmUnmapIoSpace(virtAddr,mapSize);               
  88.         }
复制代码

可以发现是直接套用了G4D对于映射信息的格式:
  1. /*lint -esym(768,_GRUB4DOS_DRIVE_MAP_SLOT::in_situ) Info 768: global struct member not referenced */
  2. typedef struct _GRUB4DOS_DRIVE_MAP_SLOT
  3. {
  4.         UCHAR from_drive;
  5.         UCHAR to_drive;                         // 0xFF indicates a memdrive
  6.         UCHAR max_head;
  7.         UCHAR max_sector:6;
  8.         UCHAR disable_lba:1;         // bit 6: disable lba
  9.         UCHAR read_only:1;                 // bit 7: read only
  10.         USHORT to_cylinder:13;         // max cylinder of the TO drive
  11.         USHORT from_cdrom:1;         // bit 13: FROM drive is CDROM(with big 2048-byte sector)
  12.         USHORT to_cdrom:1;                 // bit 14:  TO  drive is CDROM(with big 2048-byte sector)
  13.         USHORT to_support_lba:1; // bit 15:  TO  drive support LBA
  14.         UCHAR to_head;                         // max head of the TO drive
  15.         UCHAR to_sector:6;                 // max sector of the TO drive
  16.         UCHAR fake_write:1;                 // bit 6: fake-write or safe-boot
  17.         UCHAR in_situ:1;                 // bit 7: in-situ
  18.         ULONGLONG start_sector;
  19.         ULONGLONG sector_count;
  20. }GRUB4DOS_DRIVE_MAP_SLOT,*PGRUB4DOS_DRIVE_MAP_SLOT;
复制代码

重点句:
  1. // copy all GRUB4DOS drive map slots to our driver context area slot structure
  2.                                 // k - 0xE3 is the start offset of our drive map table, this negative memory range is included in our memory map
  3.                                 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。

回复

使用道具 举报

9#
发表于 2020-11-6 17:29:39 来自手机 | 显示全部楼层
2011yaya2007777 发表于 2020-11-6 17:19
sunsea:你太了!粗看了一下 ,代码从 9F000 开始从高到低搜索特定字符串。在程序搜索范围内,写特定字符串 ...
sunsea:你太了!

没看懂,是不是打错字了

嘛,反正就把所有的slot连续摆放进这个变量里就行了。然后把这个变量的两个属性设置上,确保启动器和操作系统下都能访问。然后应该就可以了。然后还需要一下这个变量在的名字空间的GUID。

感谢!
回复

使用道具 举报

10#
发表于 2020-11-6 17:35:13 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-6 17:52 编辑
2011yaya2007777 发表于 2020-11-6 17:31
抱歉,手机上发了一个牛的表情符号,结果没有了。那两个访问属性怎么设置,还的研究一下。如有人知道,可告 ...

过奖过奖了。

看了一下资料。
https://blog.csdn.net/jiangwei0512/article/details/52877055/
在这里应该就行了
  1. typedef
  2. EFI_STATUS
  3. (EFIAPI *EFI_SET_VARIABLE)(
  4.   IN  CHAR16                       *VariableName,
  5.   IN  EFI_GUID                     *VendorGuid,
  6.   IN  UINT32                       Attributes, // 就在这里,传入EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS应该就可以了。
  7.   IN  UINTN                        DataSize,
  8.   IN  VOID                         *Data
  9.   );
复制代码


随便生成了一个GUID作为名字空间的VendorGuid:
{621F0DF7-B6BB-4334-B16B-3C8AFC883B3A}

就用这个吧,应该没人重复。

然后Data就是那堆slots构成的数组,Name就叫$INT13SFGRUB4DOS这样。

希望能做参考。

————

在看了下UEFI Spec,SetVariable似乎是个Runtime Service,直接找到表然后调用就行了?具体我也不懂……

回复

使用道具 举报

11#
发表于 2020-11-6 22:19:15 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-6 22:23 编辑
2011yaya2007777 发表于 2020-11-6 17:31
抱歉,手机上发了一个牛的表情符号,结果没有了。那两个访问属性怎么设置,还的研究一下。如有人知道,可告 ...

以及还有几个可能的问题:
1,map --mem的内存盘是否会在退出UEFI环境后被释放掉,以及是否有类似于hook INT15的机制来告诉操作系统【这块内存被保留】什么的……担心后来的操作系统把仿真盘破坏掉
2,有何种手段能够欺骗bootmgfw.efi让它能够正确读取仿真盘上的bcd等关键文件……不过看样子似乎这个问题已经被解决了
回复

使用道具 举报

12#
发表于 2020-11-6 23:12:54 | 显示全部楼层
wintoflash 发表于 2020-11-6 22:58
EFI_RESERVED_MEMORY_TYPE,
EFI_LOADER_CODE,
EFI_LOADER_DATA,

是的,希望yaya尽快上传代码。
回复

使用道具 举报

13#
发表于 2020-11-7 10:45:27 | 显示全部楼层
2011yaya2007777 发表于 2020-11-7 10:41
终于搞明白了,是启动 Windows 时只认第一光驱!我的电脑内存小,平时只是测试个小空壳iso,所以老是不能重 ...

第一个问题盲猜是UEFI只告诉Windows这块内存没人用了,然后Windows把它加入可用内存列表分配使用,仅此而已。

第二个问题,根据我目前阅读到的代码:
加了--mem参数:根据slot找到镜像所在内存位置,然后登记并读写数据。
没加mem:根据slot找到【镜像所在的】【磁盘位置】,然后直接【读写磁盘】
(其实我没看懂你这个问题……
回复

使用道具 举报

14#
发表于 2020-11-7 11:59:41 来自手机 | 显示全部楼层
2011yaya2007777 发表于 2020-11-7 11:14
你已经说明白了,两种情况都可以挂载。不过第二种情况比较复杂,不像BIOS环境0x80就是第一块硬盘,在UEFI ...

先复制吧,我过会回宿舍再阅读一下代码看看具体它怎么找硬盘的。
回复

使用道具 举报

15#
发表于 2020-11-7 12:00:38 来自手机 | 显示全部楼层
wintoflash 发表于 2020-11-7 11:59
我觉得yaya想弄清楚的是,如果不加--mem,

svbus是怎么把bios下的磁盘和windows下的磁盘对上号的?

好的,我下午晚上再看看,争取写个分析帖子出来。
回复

使用道具 举报

16#
发表于 2020-11-7 17:09:16 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-7 17:13 编辑

  1.         // get list of disk class devices
  2.         Status = IoGetDeviceInterfaces(&GUID_DEVINTERFACE_DISK,NULL,0,&SymbolicLinkList);
  3.         if(!NT_SUCCESS(Status))
  4.         {
  5.                 return Status;
  6.         }

  7.         // allocate memory for read buffer
  8.         // the minimum buffer size should be 2048 bytes for one CD/DVD-ROM sector
  9.         size = 0x800;
  10.         buf = (PUCHAR)ExAllocatePoolWithTag(PagedPool,size,SVBUS_POOL_TAG);
  11.         if(buf == NULL)
  12.         {
  13.                 return STATUS_INSUFFICIENT_RESOURCES;
  14.         }

  15.         // do this for every disk in the Unicode string list
  16.         for(p = SymbolicLinkList; *p != UNICODE_NULL; p += len)
  17.         {
  18.                 // do not check our own SVBus, this can BSOD with the error "System Thread Exception not handled" if we send IRP_MJ_READ in IoCallDriver of ReadWritePhysicalDisk
  19.                 /*lint -save -e585 Warning 585: The sequence (??\) is not a valid Trigraph sequence */
  20.                 if(RtlCompareMemory(p,L"\\??\\SVBus",(SIZE_T)0x12) != 0x12)
  21.                 /*lint -restore */
  22.                 {
  23.                         // initialize device name unicode string
  24.                         RtlInitUnicodeString(&deviceNameUnicodeString,p);

  25.                         // get a pointer to the top object in the named device object's stack and a pointer to the corresponding file object
  26.                         Status = IoGetDeviceObjectPointer(&deviceNameUnicodeString,FILE_ALL_ACCESS,&FileObject,&FileDeviceObject);
  27.                         if(NT_SUCCESS(Status))
  28.                         {
  29.                                 // CDROM
  30.                                 if(DeviceExtension->Disk.VirtualDeviceType == CDROM)
  31.                                 {
  32.                                         // read possible CD001 location of virtual ISO file on physical disk
  33.                                         ByteOffset.QuadPart = (LONGLONG)DeviceExtension->Disk.ImageStartOffsetInBytes + 0x8000; //算出镜像文件首地址,然后求出特征标记所在地址
  34.                                 }
  35.                                 // HDD and FLOPPY
  36.                                 else
  37.                                 {
  38.                                         // read possible MBR location of virtual hard disk file on physical disk
  39.                                         ByteOffset.QuadPart = (LONGLONG)DeviceExtension->Disk.ImageStartOffsetInBytes;//算出镜像文件首地址,然后求出特征标记所在地址
  40.                                 }

  41.                                 // zero read buffer memory
  42.                                 RtlZeroMemory(buf,size);

  43.                                 // read / write physical disk
  44.                                 Status = ReadWritePhysicalDisk(FileDeviceObject,FileObject,IRP_MJ_READ,buf,(ULONG)size,&ByteOffset);
  45.                                 if(NT_SUCCESS(Status))
  46.                                 {
  47.                                         // CDROM
  48.                                         if(DeviceExtension->Disk.VirtualDeviceType == CDROM)
  49.                                         {
  50.                                                 // check for string "CD001"
  51.                                                 if(buf[1] == 'C' && buf[2] == 'D' && buf[3] == '0' && buf[4] == '0' && buf[5] == '1') //读写,检查标记,对就给过
  52.                                                 {
  53.                                                         // we have found a valid CDROM ISO, save file object and file device object
  54.                                                         DeviceExtension->Disk.FileObject = FileObject;
  55.                                                         DeviceExtension->Disk.FileDeviceObject = FileDeviceObject;
  56.                                                         // free read buffer memory
  57.                                                         ExFreePoolWithTag(buf,SVBUS_POOL_TAG);
  58.                                                         // free list of disks
  59.                                                         ExFreePool(SymbolicLinkList);
  60.                                                         return STATUS_SUCCESS;
  61.                                                 }
  62.                                         }
  63.                                         // HDD and FLOPPY
  64.                                         else if(DeviceExtension->Disk.VirtualDeviceType == HDD || DeviceExtension->Disk.VirtualDeviceType == FLOPPY)
  65.                                         {
  66.                                                 // check for last 2 bytes of a valid MBR
  67.                                                 if(buf[510] == 0x55 && buf[511] == 0xAA) //读写,检查标记,对就给过
  68.                                                 {
  69.                                                         // we have found a valid MBR, save file object and file device object
  70.                                                         DeviceExtension->Disk.FileObject = FileObject;
  71.                                                         DeviceExtension->Disk.FileDeviceObject = FileDeviceObject;
  72.                                                         // free read buffer memory
  73.                                                         ExFreePoolWithTag(buf,SVBUS_POOL_TAG);
  74.                                                         // free list of disks
  75.                                                         ExFreePool(SymbolicLinkList);
  76.                                                         return STATUS_SUCCESS;
  77.                                                 }
  78.                                         }
  79.                                 }

  80.                                 // we have not found a CDROM ISO or an MBR
  81.                                 // dereference the file object, this will also indirectly dereference the device object
  82.                                 ObDereferenceObject(FileObject);
  83.                         }
  84.                 }

  85.                 // get Unicode string length of physical disk
  86.                 // add 2 bytes for Unicode terminating null and continue with the next physical disk in the list
  87.                 len = wcslen(p) + 1;
  88.         }
复制代码

SVBus作者思路就两部:
1,算出镜像文件应该所在物理磁盘上的位置
2,根据位置,逐个检查物理磁盘,读指定位置,看有没有特征标记,有就给过,不再检查

跟那些0x80 0x81没有任何关系……这个思路我只能说牛逼,用最小的代码量覆盖了99%的情况……毕竟两个磁盘上同一位置都有有效标记很罕见……也意味着这个方案应该是可以移植到UEFI下的……
回复

使用道具 举报

17#
发表于 2020-11-7 20:09:11 | 显示全部楼层
wintoflash 发表于 2020-11-7 19:37
这还真是简单粗暴。
那map信息里面的CHS什么的也用不到吧,只要文件在磁盘上的扇区号或者内存地址信息就 ...

似乎还是用了,因为Windows会询问这些磁盘参数,所以Slots里是啥SVBus就填的啥。
回复

使用道具 举报

18#
发表于 2020-11-8 12:35:46 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-8 12:43 编辑
2011yaya2007777 发表于 2020-11-8 11:48
我想了解SVBus使用插槽的情况,可否上传源代码?

https://sourceforge.net/projects/svbus/
在这里直接下载,程序包里就有源代码。
搜索关键词是slots。有什么内核相关的函数看不懂可以问我。

摘录一些:

  1.         DeviceExtension->Disk.DiskGeometry.TracksPerCylinder = DriverExtension->slot[i].max_head + 1;
  2.         DeviceExtension->Disk.DiskGeometry.SectorsPerTrack = DriverExtension->slot[i].to_sector;
  3.         DeviceExtension->Disk.DiskGeometry.BytesPerSector = DeviceExtension->Disk.SectorSize;
  4.         DeviceExtension->Disk.DiskGeometry.Cylinders.QuadPart = (LONGLONG)((DeviceExtension->Disk.ImageSizeInLBAs / DeviceExtension->Disk.DiskGeometry.TracksPerCylinder) / DeviceExtension->Disk.DiskGeometry.SectorsPerTrack);
复制代码
↑CHS直接引用slot


  1.         if(DriverExtension->slot[i].from_cdrom == 1)
  2.         {
  3.                 // set device type and characteristics to CDROM
  4.                 DeviceType = FILE_DEVICE_CD_ROM;
  5.                 DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE | FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN;
  6.         }
  7.         // HDD and FLOPPY
  8.         // from_cdrom == 0
  9.         else
  10.         {
  11.                 // FLOPPY
  12.                 if(DriverExtension->slot[i].from_drive < 0x80)
  13.                 {
  14.                         // set device type and characteristics to FLOPPY
  15.                         DeviceType = FILE_DEVICE_DISK;
  16.                         DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE | FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN;
  17.                 }
  18.                 // HDD
  19.                 else
  20.                 {
  21.                         // set device type and characteristics to HDD
  22.                         DeviceType = FILE_DEVICE_DISK;
  23.                         DeviceCharacteristics = FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN;
  24.                 }
  25.         }
复制代码

↑根据from_drive判断类型。

  1.         // RAM image
  2.         if(DriverExtension->slot[i].to_drive == 0xFF)
  3.         {
  4.                 // set image type to RAM and copy image type string
  5.                 DeviceExtension->Disk.ImageType = RAM;
  6.                 swprintf(DeviceExtension->Disk.wszImageType,L"RAM");
  7.         }
  8.         // DISK image
  9.         else
  10.         {
  11.                 // set image type to DISK and copy image type string
  12.                 DeviceExtension->Disk.ImageType = DISK;
  13.                 swprintf(DeviceExtension->Disk.wszImageType,L"Disk");
  14.         }
复制代码

↑根据to_drive判断镜像所在位置。



  1.                         // do not subtract one sector for the VHD image footer, because we have a floppy image
  2.                         DeviceExtension->Disk.ImageSizeInLBAs = DriverExtension->slot[i].sector_count;
复制代码

↑计算磁盘长度。

  1.         // calculate image start offset in bytes
  2.         // start sector is always based on 512 byte sectors of the HDD
  3.         DeviceExtension->Disk.ImageStartOffsetInBytes = DriverExtension->slot[i].start_sector * 512;
复制代码
↑计算在磁盘上的起始地址。

其他参数好像没用,不过为了保持结构一致和地址不变的话还是保留吧?反正也不占多少空间。
回复

使用道具 举报

19#
发表于 2020-11-8 13:11:22 | 显示全部楼层
2011yaya2007777 发表于 2020-11-8 13:03
谢谢了。主要是我认为在 UEFI 环境下,chs 参数无用,插槽的 chs 位置被其他参数占用。看来换得做些调整 ...

Here。里面的SVBus/src文件夹。
SVBus_V1.2_20200428.rar (66.76 KB, 下载次数: 15)

我也是很好奇,都0202年了,为什么Windows还要询问磁盘的CHS……M$真的不知道几乎所有磁盘都是线性寻址了吗……0202年了不是1999年啊……


回复

使用道具 举报

20#
发表于 2020-11-9 01:14:08 来自手机 | 显示全部楼层
wuwuzz 发表于 2020-11-8 21:09
一个小插曲,关于CHS。

我认为,CHS不可或缺。从流出的BIOS/UEFI源代码来看:

很好奇一个问题,保留CHS除了兼容旧软件之外的意义在哪里?难道有固件或者软件到现在了线性寻址也给不出正确结果?

点评

是的,兼容老标准这个原因是确定无疑的。只要INT13还在,CHS就如影相随。  详情 回复 发表于 2020-11-9 09:23
回复

使用道具 举报

21#
发表于 2020-11-9 09:41:59 来自手机 | 显示全部楼层
wuwuzz 发表于 2020-11-9 09:23
是的,兼容老标准这个原因是确定无疑的。只要INT13还在,CHS就如影相随。
从代码上看,到了UEFI,似乎也 ...

可还行……那为什么不统一H255S63然后内部转成线性地址呢……还是有老的/不规范固件给不出正确结果还是咋滴……

点评

U盘(USB存储设备)内部都是转成LBA访问。 就目前知道的情况,磁盘类设备有很多种(FDD、ZIP、HDD),HS不会一样的... 而新版UEFI又新增了usb key这种(由于没有对应版本的代码可看,所以不了解它是怎么个算法)  详情 回复 发表于 2020-11-9 10:25
回复

使用道具 举报

22#
发表于 2020-11-9 11:08:52 来自手机 | 显示全部楼层
2011yaya2007777 发表于 2020-11-9 10:42
可以测试 SVBus 了。

请问这个是怎么处理映射信息传递的?拷贝进前640KB还是放置UEFI变量?需要我做什么吗
回复

使用道具 举报

23#
发表于 2020-11-9 16:25:16 | 显示全部楼层
2011yaya2007777 发表于 2020-11-9 12:06
拷贝进前640KB,直接测试就行了。

这个方案不错,劳动量变得更小了hhhh,但是问题来了,会不会有CSM或者其他一些申必情况导致这个方案出现问题?不过也可以收到报告再说吧……
回复

使用道具 举报

24#
发表于 2020-11-9 16:57:14 | 显示全部楼层
2011yaya2007777 发表于 2020-11-9 16:44
如果使用菜单变量,那后续工作就可能与 SVBus 无关了。

菜单变量是啥啊……
回复

使用道具 举报

25#
发表于 2020-11-9 18:44:08 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-9 18:45 编辑
2011yaya2007777 发表于 2020-11-9 18:16
不好意思,打错了。是采用变量...

嘛,就先这样吧,这样不用我进一步对现有驱动做修改了,用原版驱动就挺好的hhhhhhhhh。也保持兼容性,哪天哪位的BIOS对这个方案不高兴了再说吧。
回复

使用道具 举报

26#
发表于 2020-11-10 19:28:01 | 显示全部楼层
wintoflash 发表于 2020-11-10 19:07
EFI_LOADER_CODE 和 EFI_LOADER_DATA,操作系统可以自行决定是否回收。
AllocatePages分配的内存不跨页 ...

自行决定是否回收的话对我们的虚拟盘估计就比较有风险了……
回复

使用道具 举报

27#
发表于 2020-11-10 20:17:17 | 显示全部楼层
2011yaya2007777 发表于 2020-11-10 19:57
操作系统可以自行决定是否回收。那就是和引导时代码及引导时数据一样了?操作系统执行退出引导代码及数据时 ...

估计变成概率问题了……所以总感觉这样非常不安全,容易引发各种问题……
回复

使用道具 举报

28#
发表于 2020-11-10 21:04:31 | 显示全部楼层

本帖最后由 sunsea 于 2020-11-10 21:06 编辑
2011yaya2007777 发表于 2020-11-10 19:57
操作系统可以自行决定是否回收。那就是和引导时代码及引导时数据一样了?操作系统执行退出引导代码及数据时 ...

还有如果映射能映射到0xffff了那我是不是驱动里的映射插槽也要修订一下……
驱动里用的映射插槽还是这个
  1. typedef struct _GRUB4DOS_DRIVE_MAP_SLOT
  2. {
  3.         UCHAR from_drive;
  4.         UCHAR to_drive;                         // 0xFF indicates a memdrive
  5.         UCHAR max_head;
  6.         UCHAR max_sector:6;
  7.         UCHAR disable_lba:1;         // bit 6: disable lba
  8.         UCHAR read_only:1;                 // bit 7: read only
  9.         USHORT to_cylinder:13;         // max cylinder of the TO drive
  10.         USHORT from_cdrom:1;         // bit 13: FROM drive is CDROM(with big 2048-byte sector)
  11.         USHORT to_cdrom:1;                 // bit 14:  TO  drive is CDROM(with big 2048-byte sector)
  12.         USHORT to_support_lba:1; // bit 15:  TO  drive support LBA
  13.         UCHAR to_head;                         // max head of the TO drive
  14.         UCHAR to_sector:6;                 // max sector of the TO drive
  15.         UCHAR fake_write:1;                 // bit 6: fake-write or safe-boot
  16.         UCHAR in_situ:1;                 // bit 7: in-situ
  17.         ULONGLONG start_sector;
  18.         ULONGLONG sector_count;
  19. }GRUB4DOS_DRIVE_MAP_SLOT,*PGRUB4DOS_DRIVE_MAP_SLOT;
复制代码
,然后硬编码了from_drive<0x80时认为是软盘,>0xA0时认为是光盘
from to用的都还是8位的
回复

使用道具 举报

29#
发表于 2020-11-11 10:53:08 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-11 10:58 编辑
2011yaya2007777 发表于 2020-11-11 08:59
熟悉并使用过 SVBus、FiraDisk、WinVblock 的坛友,请释疑一下:
是往 windows 传递了软盘?硬盘?光盘? ...

1,有多少插槽创建多少设备,反正对于它在的那个层次(SCSI Miniport),Windows不区分,统一下发SCSI指令,区分由更高层的驱动处理
2,Imdisk工作依赖于【文件系统】(当然如果你直接指定\\.\PhysicalDrive0这种“镜像”当我没说),SVBus加载的时候(SCSI Miniport组),文件系统驱动还没有加载,只能扇区序列读。随后文件系统才到场对各个已经成型的设备进行识别。Imdisk也不认识映射插槽,所以硬要用Imdisk也可以,不过还是得有个工作在内核层次的东西处理插槽信息。
3,不在这种极端早期加载驱动,Windows就会读盘失败——SCSI Miniport这个驱动组加载完成以后Windows就用他们读盘而不是UEFI BIOS本身提供的功能读盘,所以这个时候之后再加载不出来Windows会直接BSOD掉,当年XP上很经典的0x7B还是啥的蓝屏就是这个,只不过当年是因为XP没有AHCI驱动而已。
回复

使用道具 举报

30#
发表于 2020-11-11 12:42:11 | 显示全部楼层
本帖最后由 sunsea 于 2020-11-11 12:52 编辑
2011yaya2007777 发表于 2020-11-11 12:28
一共8个插槽,from_drive=0xA0时认为是光盘。
复制的插槽结构与SVBus一致。


做PE的时候,很多都有【复杂环境下加载一二级内核,找到外置或者其他什么虚拟盘】的需求。尤其是从UD启动的时候。当然UEFI没UD了,但是如果是一些隐藏方案的话启动时认虚拟盘需求仍在。
以及做RAMOS。都需要有驱动来帮Windows认盘,毕竟对于这两个环境来说这就是系统盘,系统盘都不认的话就直接蓝屏、启动失败之类的。
SVBus,Firadisk,winvblock这类驱动就相当于XP年代的AHCI驱动,帮助Windows认出虚拟盘,就这个。

总结一下,就是【系统文件在虚拟盘上,需要驱动认盘】,SVBus干的就是帮助认盘。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-5-7 06:40

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表