flat assembler
Message board for the users of flat assembler.

Index > OS Construction > UEFI GOP->QueryMode() function doesn't execute the 2nd time

Author
Thread Post new topic Reply to topic
robstat7



Joined: 03 Apr 2024
Posts: 11
robstat7 10 Nov 2026, 09:58
Hi, in my UEFI bootloader, I am trying to find the video mode code for 1280x1024 resolution. I loop through each value of counter starting from 0 upto the total video modes and on the second iteration, `debug_msg2` doesn't get printed at all and the execution hangs. How can I go about this?

The value of counter at second iteration is 1. Register RCX contains the GOP pointer. What could be wrong here?

Code:
; Video mode code constant
MODE_CODE_INVALID = 100     ; taking an arbitrary higher mode code


section '.text' code executable readable

;
; find_mode_code_for_1280x1024_resolution
;
; This function finds the video mode code for 1280 x 1024 resolution.
;
; Args:
;   @rcx = GOP interface
;   @edx = total number of video modes
;
; Returns:
;   @eax = video mode code
;
find_mode_code_for_1280x1024_resolution:
  push rbp
  mov rbp, rsp

  sub rsp, 32

  total_video_modes equ dword [rbp - 4]
  counter equ dword [rbp - 8]
  gop equ qword [rbp - 14]
  mode_code equ dword [rbp - 18]

  mov gop, rcx
  mov total_video_modes, edx

  mov mode_code, MODE_CODE_INVALID
  mov counter, 0

.loop_start:
  mov eax, total_video_modes
  cmp counter, eax
  jae .loop_end

  ; DEBUG
  uefi_call_wrapper ConOut, OutputString, ConOut, debug_msg1

  mov rcx, gop
  mov edx, counter
  ; invoke EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode() function
  uefi_call_wrapper rcx, QueryMode, rcx, rdx, size_of_info, info

  ; DEBUG
  uefi_call_wrapper ConOut, OutputString, ConOut, debug_msg2

  mov rax, qword [info]
  mov ecx, dword [rax + \
      EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution]
  cmp ecx, 1280
  jne .free_pool
  mov ecx, dword [rax + \
      EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.VerticalResolution]
  cmp ecx, 1024
  jne .free_pool
  mov ecx, dword [rax + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelFormat]
  cmp ecx, EFI_GRAPHICS_PIXEL_FORMAT_PixelBlueGreenRedReserved8BitPerColor
  jne .free_pool

  mov eax, counter
  mov mode_code, eax
  jmp .loop_end

.free_pool:
  mov rcx, qword [info]
  uefi_call_wrapper BootServices, FreePool, rcx

.loop_next:
  inc counter
  jmp .loop_start

.loop_end:
  mov eax, MODE_CODE_INVALID 
  cmp mode_code, eax
  je .exit

  mov rcx, qword [info]
  uefi_call_wrapper BootServices, FreePool, rcx

.exit:
  mov eax, mode_code

  restore total_video_modes
  restore counter
  restore gop
  restore mode_code

  mov rsp, rbp
  pop rbp
  ret

section '.data' data readable writeable

size_of_info  dq 0
info          dq 0

debug_msg1 du "@Before calling querymode func", 13, 10, 0
debug_msg2 du "@After calling querymode func", 13, 10, 0
    


Output:
Code:
@Before calling querymode func
@After calling querymode func
@Before calling querymode func
    


Here is the UEFI library:
Code:
; Invoke a uefi function
macro uefi_call_wrapper interface, function, arg1, arg2, arg3, arg4, arg5 {
  total_arg = 0
  if ~ arg5 eq
    total_arg = total_arg + 1
    if ~ arg5 eq r10
      mov r10, arg5
    end if
  end if
  if ~ arg4 eq
    total_arg = total_arg + 1
    if ~ arg4 eq r9
      mov r9, arg4
    end if
  end if
  if ~ arg3 eq
    total_arg = total_arg + 1
    if ~ arg3 eq r8
      mov r8, arg3
    end if
  end if
  if ~ arg2 eq
    total_arg = total_arg + 1
    if ~ arg2 eq rdx
      mov rdx, arg2
    end if
  end if
  if ~ arg1 eq
    total_arg = total_arg + 1
    if ~ arg1 eq rcx
      if ~ arg1 in <ConsoleInHandle, ConIn, \
              ConsoleOutHandle, ConOut, \
              StandardErrorHandle, StdErr, \
              RuntimeServices, BootServices>
        mov rcx, arg1
      end if
    end if
  end if

  xor rax, rax
  mov al, total_arg
  if interface in <ConsoleInHandle, ConIn, ConsoleOutHandle, ConOut, \
        StandardErrorHandle, StdErr, RuntimeServices, \
        BootServices>
    mov r14, [system_table]
    mov r14, [r14 + EFI_SYSTEM_TABLE.#interface]
  else
    if ~ interface eq r14
      mov r14, interface
    end if
  end if
  if arg1 in <ConsoleInHandle, ConIn, ConsoleOutHandle, ConOut, \
        StandardErrorHandle, StdErr, RuntimeServices, BootServices>
    mov rcx, r14
  end if
  if defined EFI_GRAPHICS_OUTPUT_PROTOCOL.#function
    mov r14, [r14 + EFI_GRAPHICS_OUTPUT_PROTOCOL.#function]
  else if defined EFI_BOOT_SERVICES.#function
    mov r14, [r14 + EFI_BOOT_SERVICES.#function]
  else if defined EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.#function
    mov r14, [r14 + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.#function]
  else if defined EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.#function
    mov r14, [r14 + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.#function]
  else
    mov r14, [r14 + function]
  end if

  call uefi_func
}

;
; Library functions
;

section '.text' code executable readable

;
; uefi_func
;
; Note: See the Microsoft's x64 ABI conventions.
;
uefi_func:
  ; Save stack pointer
  mov qword [uefi_rsptmp], rsp
  ; Set up new aligned stack:
  ; As per the Microsoft's x64 calling convention, the stack pointer
  ; must be 16-byte aligned at the point of any function call.
  and esp, 0FFFFFFF0h
  ; Alignment check on arguments:
  ; if total_arg is less than 5, we don't need any stack pointer
  ; alignment. Reason: we only pass 5th and further arguments via the
  ; stack and it might or might not misalign it.
  cmp eax, 5    ; al contains the total_arg from uefi_call_wrapper macro
  jb .before_call
  bt eax, 0
  jnc @f
  push rax      ; Push dummy rax reg value for stack alignment purpose
  ; Arguments
@@:     cmp al, 5
  jb @f
  push r10
@@:
.before_call:
  ; 32 bytes (shadow) space for
  ; r9
  ; r8
  ; rdx
  ; rcx
  sub rsp, 4*8
  ; call function
  call r14
  ; restore old stack
  mov rsp, qword [uefi_rsptmp]
  ret


section '.data' data readable writeable

image_handle  dq 0
system_table  dq 0

uefi_rsptmp   dq 0
    
Post 10 Nov 2026, 09:58
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21208
Location: In your JS exploiting you and your system
revolution 10 Nov 2026, 10:54
The alignment for these doesn't look right
Code:
  gop equ qword [rbp - 14]
  mode_code equ dword [rbp - 18]    
gop overlaps counter. Is that intentional?
Post 10 Nov 2026, 10:54
View user's profile Send private message Visit poster's website Reply with quote
robstat7



Joined: 03 Apr 2024
Posts: 11
robstat7 10 Nov 2026, 11:49
No. I am sorry. I accidentally calculated 6 bytes instead of 8 for `gop` variable.
The following correction worked!

Code:
gop equ qword [rbp - 16]
mode_code equ dword [rbp - 20] 
    


Thank you so much.
Post 10 Nov 2026, 11:49
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.