gnu-efi开发:QEMU中Hello World输出乱码问题求助
gnu-efi开发Hello World乱码问题
我刚接触gnu-efi开发,尝试为QEMU编写一个简单的Hello World程序。官方提供的示例程序运行正常,但当我复用其中一个示例的C代码自行构建后,在QEMU shell中输出了奇怪的类中文字符。以下是我的Makefile和C代码片段:
Makefile
ARCH = x86_64 CC = cc LD = ld OBJCOPY = objcopy OBJS = myapp.o TARGET = myapp.efi # Use your local gnu-efi build GNUEFI_DIR = gnu-efi EFIINC = $(GNUEFI_DIR)/inc EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol EFILIB = $(GNUEFI_DIR)/x86_64 EFI_CRT_OBJS = $(EFILIB)/gnuefi/crt0-efi-$(ARCH).o EFI_LDS = $(GNUEFI_DIR)/gnuefi/elf_$(ARCH)_efi.lds CFLAGS = $(EFIINCS) -fno-stack-protector -fpic \ -fshort-wchar -mno-red-zone -Wall ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER endif LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \ -Bsymbolic -L $(EFILIB)/lib -L $(EFILIB)/gnuefi all: check_gnuefi $(TARGET) myapp.so: $(OBJS) $(LD) $(LDFLAGS) $(EFI_CRT_OBJS) $(OBJS) -o $@ -lefi -lgnuefi %.efi: %.so objcopy -j .text -j .sdata -j .data -j .dynamic \ -j .dynsym -j .rel -j .rela -j .reloc \ --target=efi-app-$(ARCH) $^ $@ %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f $(OBJS) *.so *.efi OVMF_CODE ?= OVMF_CODE_4M.fd OVMF_VARS ?= OVMF_VARS_4M.fd .PHONY: check_gnuefi build-gnuefi check_gnuefi: @if [ -f "$(EFI_CRT_OBJS)" ]; then \ echo "Found $(EFI_CRT_OBJS) — OK"; \ else \ echo "crt0 not found in $(EFILIB)/gnuefi — run 'make build-gnuefi' to build the gnu-efi subdir or install a system package"; exit 1; \ fi build-gnuefi: @echo "Building gnu-efi subdir (may require tools & privileges)..."; \ $(MAKE) -C $(GNUEFI_DIR) || { echo 'Failed to build gnu-efi'; exit 1; } test: $(TARGET) mkdir -p test-disk cp $(TARGET) test-disk/BOOTX64.EFI qemu-system-x86_64 \ -drive if=pflash,format=raw,readonly=on,file=$(CURDIR)/$(OVMF_CODE) \ -drive if=pflash,format=raw,file=$(CURDIR)/$(OVMF_VARS) \ -drive file=fat:rw:test-disk,format=raw,media=disk \ -nographic -serial mon:stdio -m 256M rm -rf test-disk .PHONY: all clean test
C代码
#include <efi.h> #include <efilib.h> EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { SIMPLE_TEXT_OUTPUT_INTERFACE *conout; InitializeLib(image, systab); conout = systab->ConOut; uefi_call_wrapper(conout->OutputString, 2, conout, u"Hello World!\n"); return EFI_SUCCESS; }
问题原因与修复方案
问题核心是EFI输出接口要求UTF-16编码的宽字符字符串,你代码中使用的u""字符串在编译处理时不符合EFI的CHAR16规范,加上换行符的编码问题,导致输出乱码。
修复方案1:使用gnu-efi提供的Print宏(推荐)
Print宏会自动处理字符串编码和格式化逻辑,无需手动调用底层接口:
#include <efi.h> #include <efilib.h> EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { InitializeLib(image, systab); Print(L"Hello World!\n"); return EFI_SUCCESS; }
修复方案2:修正手动调用的字符串格式
如果坚持使用OutputString,需要将字符串前缀改为L""(符合EFI宽字符要求),确保是正确的UTF-16编码:
#include <efi.h> #include <efilib.h> EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { SIMPLE_TEXT_OUTPUT_INTERFACE *conout; InitializeLib(image, systab); conout = systab->ConOut; uefi_call_wrapper(conout->OutputString, 2, conout, L"Hello World!\n"); return EFI_SUCCESS; }
另外,你的Makefile中已经包含了-fshort-wchar参数,这个参数确保wchar_t是16位(匹配EFI的CHAR16类型),无需额外修改。
内容的提问来源于stack exchange,提问作者Malaika
相关产品推荐
相关产品推荐

