最近需要在 Shell 下读取 MSR 设置,然后发现没有顺手的工具,于是写了一个。
最主要的工作是AsmReadMsr64 和AsmWriteMsr64 函数来完成的,所以整体上并不复杂,代码如下:
/** @file A simple, basic, application showing how the Hello application could be built using the "Standard C Libraries" from StdLib. Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include <Library/BaseLib.h> #include <Uefi.h> #include <Library/UefiLib.h> #include <Library/PrintLib.h> #include <Library/ShellCEntryLib.h> extern EFI_BOOT_SERVICES *gBS; BOOLEAN WriteOpt=FALSE; BOOLEAN ReadOpt=FALSE; //Copied from UDK2017\UefiCpuPkg\Include\Register\Msr\SandyBridgeMsr.h /** Package. PP0 Balance Policy (R/W) See Section 14.9.4, "PP0/PP1 RAPL Domains.". @param ECX MSR_SANDY_BRIDGE_PP0_POLICY (0x0000063A) @param EAX Lower 32-bits of MSR value. @param EDX Upper 32-bits of MSR value. <b>Example usage</b> @code UINT64 Msr; Msr = AsmReadMsr64 (MSR_SANDY_BRIDGE_PP0_POLICY); AsmWriteMsr64 (MSR_SANDY_BRIDGE_PP0_POLICY, Msr); @endcode @note MSR_SANDY_BRIDGE_PP0_POLICY is defined as MSR_PP0_POLICY in SDM. **/ #define MSR_SANDY_BRIDGE_PP0_POLICY 0x0000063A void PrintUsage() { Print(L"******************************************\n"); Print(L"* MSR Read & Write utility for KBL *\n"); Print(L"* Powered by www.lab-z.com *\n"); Print(L"* 11/14/2017 Version 0.5 *\n"); Print(L"* Usage: *\n"); Print(L"* Ex1:read MSR *\n"); Print(L"* msrtest -r 63A *\n"); Print(L"* Ex2:write MSR *\n"); Print(L"* msrtest -w 63A 11 *\n"); Print(L"******************************************\n"); } /*** Demonstrates basic workings of the main() function by displaying a welcoming message. Note that the UEFI command line is composed of 16-bit UCS2 wide characters. The easiest way to access the command line parameters is to cast Argv as: wchar_t **wArgv = (wchar_t **)Argv; @param[in] Argc Number of argument tokens pointed to by Argv. @param[in] Argv Array of Argc pointers to command line tokens. @retval 0 The application exited normally. @retval Other An error occurred. ***/ INTN EFIAPI ShellAppMain ( IN UINTN Argc, IN CHAR16 **Argv ) { UINT64 MsrValue; UINT32 MsrAddr; if (Argc<2) { PrintUsage(); return 0; } if ((StrStr(Argv[1],L"-w")!=NULL) || (StrStr(Argv[1],L"-W")!=NULL)) { WriteOpt=TRUE; if (Argc!=4) { PrintUsage(); return 0; } MsrAddr=StrHexToUintn(Argv[2]) & 0xFFFFFFFF; MsrValue=StrHexToUint64(Argv[3]); AsmWriteMsr64(MsrAddr,MsrValue); Print(L"Write MSR[%X] as %lX\n",MsrAddr,MsrValue); } if ((StrStr(Argv[1],L"-r")!=NULL) || (StrStr(Argv[1],L"-R")!=NULL)) { ReadOpt=TRUE; if (Argc!=3) { PrintUsage(); return 0; } MsrAddr=StrHexToUintn(Argv[2]) & 0xFFFFFFFF; MsrValue=AsmReadMsr64(MsrAddr); Print(L"MSR[%X]=%lX\n",MsrAddr,MsrValue); } return 0; }
在KBL-R HDK 上运行结果如下:
完整代码下载:
编译好的 X64 EFI 代码:
请问这个KBL-R HDK是什么?博主的实验机吗?最近一直在寻找一个方便的测试环境,用QEMU经常一些结果没办法得到。
硬件实体机的,虚拟机多多少少还是有点问题,最新的一些东西没有办法模拟的。
這個可以寫入MSR嗎?
可以的,你可以试试,shell 下写入, windows 中 rw 检查
這個tool 可以讀出所有core上MSR ? 可以指定core number嗎?
不行,因为UEFI Shell 下只有一个 Core 是活的,获得的 MSR 只是这个 Core 上面的。
请教您一个问题.
如果这个msr是一个不存在或者是一个读保护的msr, 这个时候程序会卡住.
怎么解决这个问题呢?
有些 MSR 或者内存在访问的时候会 hang 或者导致重启,唯一的办法就不去访问。