如何从 EFI 棒更改 msr 0x199?
How to make changes to msr 0x199 from EFI stick?
我有一台没有电池的macbookpro11,3。当电池被移除时,固件将 CPU 节流到一半速度。在 Windows 中,我可以使用 Throttlestop 覆盖它以关闭 BD PROCHOT 并将乘数设置为 25。我想从 EFI 执行此操作,以便以正常速度启动和更新 运行。
基于更新 0x3a 寄存器的 rEFInd 的源代码,我编写了这个程序,但是当 BD PROCHOT 在引导至 Windows 后被正确禁用时,乘数不是。
#include "../include/tiano_includes.h"
static VOID DisablePROCHOT(VOID)
{
UINT32 msr = 0x1FC;
UINT32 low_bits = 0, high_bits = 0;
__asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));
// lowest bit is BD PROCHOT
low_bits &= ~(1 << 0);
__asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
} // VOID DisablePROCHOT()
static VOID SetMultiplier25(VOID)
{
UINT32 msr = 0x199;
UINT32 low_bits = 0, high_bits = 0;
__asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));
// second lowest byte is multiplier
// 25 is .... xxxxxxxx 00011001 xxxxxxxx
low_bits |= 1 << 8;
low_bits &= ~(1 << 9);
low_bits &= ~(1 << 10);
low_bits |= 1 << 11;
low_bits |= 1 << 12;
low_bits &= ~(1 << 13);
low_bits &= ~(1 << 14);
low_bits &= ~(1 << 15);
__asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
} // VOID SetMultiplier25()
EFI_STATUS
EFIAPI
efi_main (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
DisablePROCHOT();
SetMultiplier25();
return EFI_SUCCESS;
}
使用 rdmsr 从 EFI 读取寄存器似乎显示两者都设置正确但是当引导到 Windows 而 0x1FC 的位 0 正确设置时存储在 0x199 中的乘数与默认值 12 相同时我预计它是 25.
默认值
这些是标准启动后的值 Windows(来自 RWEverything)
调用程序后的结果
在调用 Windows 引导加载程序之前从 EFI shell 调用了程序 bootmgfw.efi
0x1FC 已更新,0x199 未更新。
使用 Windows 中的 RWEverything 更新 0x199 会正确更改乘数,因此我相当确定它是正确的寄存器。
由于这是我的第一个 EFI(或 C)程序,我可能忽略了一些琐碎的事情。
您必须创建一个循环并在每次循环中更改处理器关联。然后你每次通过循环为每个线程(CPU1,CPU2,CPU3,CPU4)做一个wrmsr。在 Windows 你使用这个函数。
https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setthreadaffinitymask
启动后,Windows 会更改 MSR 0x199 中的值,因此在启动后查看 MSR 0x199 中的值并不能证明任何事情。
为了简化事情,您可以在 SetMultiplier 中执行此操作,
low_bits = 0x1900
我有一台没有电池的macbookpro11,3。当电池被移除时,固件将 CPU 节流到一半速度。在 Windows 中,我可以使用 Throttlestop 覆盖它以关闭 BD PROCHOT 并将乘数设置为 25。我想从 EFI 执行此操作,以便以正常速度启动和更新 运行。
基于更新 0x3a 寄存器的 rEFInd 的源代码,我编写了这个程序,但是当 BD PROCHOT 在引导至 Windows 后被正确禁用时,乘数不是。
#include "../include/tiano_includes.h"
static VOID DisablePROCHOT(VOID)
{
UINT32 msr = 0x1FC;
UINT32 low_bits = 0, high_bits = 0;
__asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));
// lowest bit is BD PROCHOT
low_bits &= ~(1 << 0);
__asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
} // VOID DisablePROCHOT()
static VOID SetMultiplier25(VOID)
{
UINT32 msr = 0x199;
UINT32 low_bits = 0, high_bits = 0;
__asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));
// second lowest byte is multiplier
// 25 is .... xxxxxxxx 00011001 xxxxxxxx
low_bits |= 1 << 8;
low_bits &= ~(1 << 9);
low_bits &= ~(1 << 10);
low_bits |= 1 << 11;
low_bits |= 1 << 12;
low_bits &= ~(1 << 13);
low_bits &= ~(1 << 14);
low_bits &= ~(1 << 15);
__asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
} // VOID SetMultiplier25()
EFI_STATUS
EFIAPI
efi_main (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
DisablePROCHOT();
SetMultiplier25();
return EFI_SUCCESS;
}
使用 rdmsr 从 EFI 读取寄存器似乎显示两者都设置正确但是当引导到 Windows 而 0x1FC 的位 0 正确设置时存储在 0x199 中的乘数与默认值 12 相同时我预计它是 25.
默认值
这些是标准启动后的值 Windows(来自 RWEverything)
调用程序后的结果
在调用 Windows 引导加载程序之前从 EFI shell 调用了程序 bootmgfw.efi
0x1FC 已更新,0x199 未更新。
使用 Windows 中的 RWEverything 更新 0x199 会正确更改乘数,因此我相当确定它是正确的寄存器。
由于这是我的第一个 EFI(或 C)程序,我可能忽略了一些琐碎的事情。
您必须创建一个循环并在每次循环中更改处理器关联。然后你每次通过循环为每个线程(CPU1,CPU2,CPU3,CPU4)做一个wrmsr。在 Windows 你使用这个函数。
https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setthreadaffinitymask
启动后,Windows 会更改 MSR 0x199 中的值,因此在启动后查看 MSR 0x199 中的值并不能证明任何事情。
为了简化事情,您可以在 SetMultiplier 中执行此操作,
low_bits = 0x1900