很早之前,BIOS如果想把一些值传递给OS,通常都是使用CMOS的。但是这样的方法有着下面的缺点:复杂度高,需要和使用位置的人协商,否则没人知道你放在CMOS中什么地方
不确定性大,可能会在代码中冲突,无法确定别人是否也用到你选择的那个CMOS位
每次传递值少,CMOS一般也就128 BYTES,很容易耗尽。
现在进化到了UEFI的时代,可以在 Shell 上将一些内容存放在内存中,然后轻松的传输到Windows中。这里只是演示这种做法,总体来说还是非常简单的。
最关键的函数就是下面这个:
Status = pBS->AllocatePool(EfiReservedMemoryType, Hdr1->Length, &Ptr);
#include <Uefi.h> #include <Library/UefiLib.h> #include <Library/ShellCEntryLib.h> #include <stdio.h> #include <stdlib.h> #include <wchar.h> #include <Protocol/EfiShell.h> #include <Library/ShellLib.h> #include <Protocol/SimpleFileSystem.h> #include <Protocol/BlockIo.h> #include <Library/DevicePathLib.h> #include <Library/HandleParsingLib.h> #include <Library/SortLib.h> #include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> extern EFI_SYSTEM_TABLE *gST; extern EFI_BOOT_SERVICES *gBS; int EFIAPI main ( IN int Argc, IN char **Argv ) { EFI_STATUS Status; UINT8 *Buffer; Status = gBS -> AllocatePool (EfiACPIMemoryNVS, 0x100 , & Buffer); * Buffer = 'L'; *(Buffer+1) = 'A'; *(Buffer+2) = 'B'; *(Buffer+3) = '-'; *(Buffer+4) = 'Z'; *(Buffer+5) = '.'; *(Buffer+6) = 'C'; *(Buffer+7) = 'O'; *(Buffer+8) = 'M'; *(Buffer+9) = '1'; printf("Memory1 [%x]\n",Buffer); //Status = gBS -> FreePool (Buffer); Status = gBS -> AllocatePool (EfiReservedMemoryType, 0x100 , & Buffer); * Buffer = 'L'; *(Buffer+1) = 'A'; *(Buffer+2) = 'B'; *(Buffer+3) = '-'; *(Buffer+4) = 'Z'; *(Buffer+5) = '.'; *(Buffer+6) = 'C'; *(Buffer+7) = 'O'; *(Buffer+8) = 'M'; *(Buffer+9) = '2'; printf("Memory2 [%x]\n",Buffer); return EFI_SUCCESS; }
再检查一下E820 Table,可以看到放置字符串的内存已经被标记为占用
之后,我们在实体机器上运行,首先还是shell下面写,然后到Windows中读取对应的内存。可以看到我们在对应的内存中能够看到写入的String.
因此,这个方法是可行的。
代码下载
Mem2OS
站长您好,您的文章对我帮助很大!这一段代码最后还是编译成了efi文件在shell下运行的吧?
如果用真机的话,在shell中运行之后要怎么才能进入windows呢?我是win8.1,谢谢!
运行之后,进入 fs0:/efi/boot/ 里面会有 Bootia32.efi 或者 bootx64.efi 这样的应用程序,执行它既可进入 windows
你好,站长,请教下Windows下的内存地址你是如何确定的呢?
另外,你这种方式,如果系统重启,内存里写入的字符串就会丢失吧。
原理上说就是写入到一个固定的物理地址,然后把这个位置标记成不可访问,然后 windows 就不会碰这个位置了。在Windows中访问这个固定的物理地址即可。重启系统就会丢失。
你好站长,看了你的文章帮助很大,请教一下,在shell中传值给Windows,如何向固定的物理地址写呢?比如,我想向内存位置0x600写入buffer数据,如何写?
AllocatePool好像只能指定type,无法指定具体的值吧?
你好,请问shell下E820 Table如何打印出来?
打印出所在内存,然后直接用命令看对应的内存位置
请问如何查看E820 Table
目前 E820 Table 已经不存在了啊。对于这个问题推荐你看一下 “Step to UEFI (155)系统保留内存探究” 和 “Step to UEFI Shell (5)—-获得Shell下内存分配状况”
站长好。
倒数第二和倒数第三图片dmem.efi 工具在您的哪篇博文可以找到,感觉很有用的工具,想编译出来使用。
dmem 4c4f90 -b
Shell 自带的,不是第三方的。