简介
在Source Debug功能未就绪前。我们可以通过串口,输出一些信息,便于我们追踪和分析代码。
SerialDebug.asm
OVMF在SerialDebug.asm中提供了,初始化串口的功能,默认未加载相关代码。根据ResetVector.nasmb(OvmfPkg\ResetVector\ResetVector.nasmb)中代码逻辑,我们只需定义宏DEBUG_SERIAL即可,如下:
%define DEBUG_SERIAL %ifdef DEBUG_PORT80 %include "Port80Debug.asm" %elifdef DEBUG_SERIAL %include "SerialDebug.asm" %elif 0 ; Set ^ this to 1 to enable postcodes on the qemu debug console. ; Disabled by default because it is incompatible with SEV-ES/SEV-SNP and TDX. %include "QemuDebugCon.asm" %else %include "DebugDisabled.asm" %endif配置初始化串口函数debugInitialize
OVMF平台默认在函数EarlyInit16中才初始化串口(使用函数debugInitialize)。我们可以将它提前,理论上CPU可以执行指令后,就可以初始化串口了。因此我们将debugInitialize放在EarlyBspInitReal16处即可,如下:
; ; @param[out] DI 'BP' to indicate boot-strap processor ; EarlyBspInitReal16: debugInitialize mov di, 'BP' jmp short Main16这样我们从EarlyBspInitReal16就可以打印信息道串口了,比如:
; ; @param[out] DI 'BP' to indicate boot-strap processor ; EarlyBspInitReal16: debugInitialize debugShowCharacter 'J' debugShowCharacter 'a' debugShowCharacter 's' debugShowCharacter 'o' debugShowCharacter 'n' debugShowCharacter 'S' debugShowCharacter 't' debugShowCharacter 'u' debugShowCharacter 'd' debugShowCharacter 'y' debugShowCharacter ':' debugShowCharacter ' ' debugShowCharacter 'E' debugShowCharacter 'a' debugShowCharacter 'r' debugShowCharacter 'l' debugShowCharacter 'y' debugShowCharacter 'B' debugShowCharacter 's' debugShowCharacter 'p' debugShowCharacter 'I' debugShowCharacter 'n' debugShowCharacter 'i' debugShowCharacter 't' debugShowCharacter 'R' debugShowCharacter 'e' debugShowCharacter 'a' debugShowCharacter 'l' debugShowCharacter 'y' debugShowCharacter '1' debugShowCharacter '6' debugNewline mov di, 'BP' jmp short Main16串口输出如下:
JasonStudy: EarlyBspInitRealy161632b1 f1 SecCoreStartupWithStack(0xFFFCC000, 0x820000)Debug Timer: FSB Clock=1000000000Debug Timer: Divisor=2Debug Timer: Frequency=500000000Debug Timer: InitialCount=50000000Send INITbreakpacket and try to connect the HOST(Intel(R)UDK Debugger Tool v1.5)...debugInitialize
这个函数用于初始化串口0x3f8,主要在相应的串口寄存器中配置以下信息:
- 设置数据格式
- 配置波特率
;//--------------------------------------------- ;// UART Register Offsets ;//--------------------------------------------- %define BAUD_LOW_OFFSET 0x00 %define BAUD_HIGH_OFFSET 0x01 %define IER_OFFSET 0x01 %define LCR_SHADOW_OFFSET 0x01 %define FCR_SHADOW_OFFSET 0x02 %define IR_CONTROL_OFFSET 0x02 %define FCR_OFFSET 0x02 %define EIR_OFFSET 0x02 %define BSR_OFFSET 0x03 %define LCR_OFFSET 0x03 %define MCR_OFFSET 0x04 %define LSR_OFFSET 0x05 %define MSR_OFFSET 0x06 ;//--------------------------------------------- ;// UART Register Bit Defines ;//--------------------------------------------- %define LSR_TXRDY 0x20 %define LSR_RXDA 0x01 %define DLAB 0x01 %define DEFAULT_COM_BASE 0x3f8 %define DEFAULT_BPS 115200 %define DEFAULT_DATA 8 %define DEFAULT_STOP 1 %define DEFAULT_PARITY 0 %define DEFAULT_BREAK_SET 0 %define SERIAL_DEFAULT_LCR ( \ (DEFAULT_BREAK_SET << 6) | \ (DEFAULT_PARITY << 3) | \ (DEFAULT_STOP << 2) | \ (DEFAULT_DATA - 5) \ ) %define SERIAL_PORT_IO_BASE_ADDRESS DEFAULT_COM_BASE %macro outToSerialPort 2 mov dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1) mov al, %2 out dx, al %endmacro %macro debugInitialize 0 jmp real16InitDebug real16InitDebugReturn: %endmacro real16InitDebug: ; ; Set communications format ; outToSerialPort LCR_OFFSET, ((DLAB << 7) | SERIAL_DEFAULT_LCR) ; ; Configure baud rate ; outToSerialPort BAUD_HIGH_OFFSET, ((115200 / DEFAULT_BPS) >> 8) outToSerialPort BAUD_LOW_OFFSET, ((115200 / DEFAULT_BPS) & 0xff) ; ; Switch back to bank 0 ; outToSerialPort LCR_OFFSET, SERIAL_DEFAULT_LCR jmp real16InitDebugReturn