Step to UEFI (40) ----- 从Shell下向Windows传值

很早之前,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;
}

 

运行结果(虚拟机下面的测试)
mo1

直接查看,可以看到确实在内存中写入了
mo2

mo3

再检查一下E820 Table,可以看到放置字符串的内存已经被标记为占用
mo4

之后,我们在实体机器上运行,首先还是shell下面写,然后到Windows中读取对应的内存。可以看到我们在对应的内存中能够看到写入的String.
mo5

mo6

因此,这个方法是可行的。

代码下载
Mem2OS

Step to UEFI (40) ----- 从Shell下向Windows传值》上有 7 条评论

  1. wzy

    站长您好,您的文章对我帮助很大!这一段代码最后还是编译成了efi文件在shell下运行的吧?
    如果用真机的话,在shell中运行之后要怎么才能进入windows呢?我是win8.1,谢谢!

    回复
    1. ziv2013 文章作者

      运行之后,进入 fs0:/efi/boot/ 里面会有 Bootia32.efi 或者 bootx64.efi 这样的应用程序,执行它既可进入 windows

      回复
  2. Bioser

    你好,站长,请教下Windows下的内存地址你是如何确定的呢?
    另外,你这种方式,如果系统重启,内存里写入的字符串就会丢失吧。

    回复
    1. ziv2013 文章作者

      原理上说就是写入到一个固定的物理地址,然后把这个位置标记成不可访问,然后 windows 就不会碰这个位置了。在Windows中访问这个固定的物理地址即可。重启系统就会丢失。

      回复
  3. jack

    你好站长,看了你的文章帮助很大,请教一下,在shell中传值给Windows,如何向固定的物理地址写呢?比如,我想向内存位置0x600写入buffer数据,如何写?
    AllocatePool好像只能指定type,无法指定具体的值吧?

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注