From: HAL在Kernel和硬件之间
HAL在抽象什么?
HAL位于内核最底层。“与硬件直接打交道“的这一层被称为硬件抽象层。顾名思义,Windows内核希望把硬件相关的代码放在HAL模块,而这似乎与WRK众多amd64或x86目录相违背。
注意,任何代码期望做到完美的抽象也许是不合理的。HAL只是在抽象和硬件最相关的处理器、中断、电源管理等,对于更上层的执行体,没办法全部取代。正如执行体中依然会在多处对于x86和amd64架构分别处理,这些并不适合放在HAL.
例如KeGetCurrentThread函数:
官方解释: Windows Kernel-Mode HAL Library
Windows runs on many different configurations of the personal computer. Each configuration requires a layer of software that interacts between the hardware and the rest of the operating system. Because this layer abstracts (hides) the low-level hardware details from drivers and the operating system, it is called the hardware abstraction layer (HAL).
HAL像是主板驱动
对于不同主板,对应着不同厂商,同时处理器、中断、电源管理和IO接口等都是特定的,HAL就像是在适配主板。当然把HAL比作了"主板驱动"并不完全合适,因为主板驱动真的包含驱动程序。
谁在调用HAL?
Ntoskrnl.exe导入表查看调用HAL哪些API. 内核和驱动程序都会使用HAL.
内核和驱动程序如何访问硬件?
按照HAL的定义,内核和驱动程序并不能直接访问硬件,比如用IO指令访问显存或启动CPU.
这些访问硬件的动作被封装在HAL里面。
HAL以什么形态存在?
DLL.
%WINDOWS%\system32\hal.dll (不同硬件平台有差异)
在Windows Vista和Windows Server 2008之前,不同平台的HAL DLL是确定的,这之后,HAL是在启动过程动态确定的。具体参考:Vista and later 内核和HAL
不同类型的HAL
From: Windows内核原理与实现
不同HAL差异在于: 单核/多核、中断控制器、电源接口、IO接口
HAL和内核需要匹配
对于Windows XP和Windows Server 2003, HAL和内核文件必须是匹配的,否则,可能出现不能启动。
The operating system image and HAL must be kept in sync at all times. Therefore, if you use a checked version of the operating system image, you must also use the checked version of the HAL (and vice versa). Failure to keep a system's operating system image and HAL coordinated can make the system unbootable.
具体参阅: Installing Just the Checked Operating System and HAL (For Windows XP and Windows Server 2003)
Android HAL
不要和它混淆了,Android HAL是因为Linux内核GPL license必须开源会损坏厂商利益,在用户模式以动态链接库达到隐藏代码的目的,和Windows HAL有很大差异.
HAL API
Windows内核--WRK和真实的Windows内核源代码差多少?(1.3) 有提到wrkamd64.exe导入表中依赖HAL API如下。
HAL内部实现
可参阅ReactOS提供HAL的源代码。
例如x86架构Flush TLB的HAL实现如下,里面读写了x86架构相关的寄存器,如cr3, cr4等。
VOID
NTAPI
HalpFlushTLB(VOID)
{
ULONG_PTR Flags, Cr4;
INT CpuInfo[4];
ULONG_PTR PageDirectory;
//
// Disable interrupts
//
Flags = __readeflags();
_disable();
//
// Get page table directory base
//
PageDirectory = __readcr3();
//
// Check for CPUID support
//
if (KeGetCurrentPrcb()->CpuID)
{
//
// Check for global bit in CPU features
//
__cpuid(CpuInfo, 1);
if (CpuInfo[3] & 0x2000)
{
//
// Get current CR4 value
//
Cr4 = __readcr4();
//
// Disable global bit
//
__writecr4(Cr4 & ~CR4_PGE);
//
// Flush TLB and re-enable global bit
//
__writecr3(PageDirectory);
__writecr4(Cr4);
//
// Restore interrupts
//
__writeeflags(Flags);
return;
}
}
//
// Legacy: just flush TLB
//
__writecr3(PageDirectory);
__writeeflags(Flags);
}