Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

UEFI boot basics

175 views
Skip to first unread message

James Harris

unread,
Nov 24, 2023, 12:59:52 PM11/24/23
to
Here are some notes on getting UEFI to boot one's own code.

To be clear about where the code below is intended to fit into an OS
boot process the idea is to boot the same OS by various means such as,
in simple terms,

BIOS --> my BIOS bootloader \
PXE --> my PXE bootloader } my OS
UEFI --> my UEFI bootloader /

and this thread is intended to be about the UEFI bootloader part.

Furthermore, while I can add some comments later about a development
environment and accessing a boot filesystem but this post is just about
getting started with a UEFI Hello World. There's already plenty in here
to make the post over-long as it is.

There are specs for UEFI (and ACPI) at

https://uefi.org/specifications

I'll refer to sections of what is currently the latest spec, i.e. 2.10.

UEFI documents are not easy reading. The basic spec, alone, is something
like 2,000 pages and obscure.

To make things worse, I've seen tutorials which add further libraries.
Such libraries are intended 'to make things easier' but they give a
programmer more to learn and make it hard to tell what is UEFI and what
is an added library. I wanted to find out about the fundamentals of UEFI
itself so what I'll describe is a relatively low-level approach.

Perhaps the best place to start is the video at

https://youtu.be/XHH4VnHbsVc

and other videos by the same (very patient!) content creator.

At least in my test environment I found that even persuading UEFI to run
code was a major undertaking. For too long the boot process led to
nothing happening at all. No output, no error message, no response of
any kind. For a long while I couldn't tell whether my code had even been
booted. So getting to the point where one can output text is crucial:
once one can write text to the display then one has a chance of
developing and debugging.

With that said here's UEFI code (in Nasm assembly syntax) to write a
Hello message to the screen. I'll walk through it, below.

efi_main is:



;Called with x64 ms abi
; RCX = image
; RDX = systab

global efi_main
efi_main:

push rbp
mov rbp, rsp
sub rsp, 32
mov r10, rdi ;image
mov r11, rsi ;systab

lea rdx, [rel msg_hello]
mov rcx, [r11 + efi_systab.conout]
mov rax, [rcx + efi_stop.OutputString]
call rax

add rsp, 32
pop rbp
ret

section .data

msg_hello: dw __?utf16?__("Hello 64 UEFI..."), 13, 10, 0



The first thing to say is that the design of UEFI appears to be heavily
influenced by Microsoft. As such, the string to be printed needs CR as
well as LF to go to the start of a new line. Also, the file which we
want UEFI to boot needs to be in PE format. There's no option of flat
binary or ELF etc.

However, once one's own bootloader is running it can load the OS from
whatever type of file one wants. In other words, the OS loader has to be
in PE format but what it loads can be of some other format as required.

When UEFI calls our code and when we call UEFI routines we naturally
have to stick to the expected calling conventions. They have to match
the CPU and mode. For 64-bit x86 booting see section 2.3.4. which is
about x64 Platforms.

The spec says that a caller must always call with the stack 16-byte
aligned. One thing I haven't found out is whether that means the stack
should be 16-byte aligned before or after the call instruction.
(Naturally, the call instruction will add 8 bytes to the stack.) The
above code assumes 'before'. So pushing RBP will realign the stack. But
that needs to be revisited.

One thing UEFI gives the booted code is a pointer to the System Table.
The table is documented in section 4. It starts with the following
fields. (I included only as far as I needed.)

struc efi_systab ;UEFI system table
.hdr: resb efi_hdr_size
.fvend: resq 1 ;FirmwareVendor
.frev: resd 1 ;FirmwareRevision
resd 1 ;padding
.coninh: resq 1 ;ConsoleInHandle
.conin: resq 1 ;ConIn
.conouth: resq 1 ;ConsoleOutHandle
.conout: resq 1 ;ConOut
endstruc

The header is


struc efi_hdr ;Generic header
.Signature: resq 1
.Revision: resd 1
.HeaderSize: resd 1
.CRC32: resd 1
resd 1 ;reserved
endstruc

A note for anyone not familiar with C: where the spec in section 4.3.1 says

CHAR16 *FirmwareVendor;
UINT32 FirmwareRevision;

whereas FirmwareRevision in the second line is uint32, as you might
expect, the asterisk on the first line indicates that FirmwareVendor is
a /pointer/ to the stated type, char16, and so in this case the field is
64-bit.

Going back to the code, the System Table's conout field is a pointer to
a 'simple text output' (STO) table for the console, i.e. the screen at
boot time. An STO table includes the following fields.

struc efi_stop ;UEFI simple text output protocol
.Reset: resq 1
.OutputString: resq 1
.TestString: resq 1
.QueryMode: resq 1
.SetMode: resq 1
.SetAttribute: resq 1
.ClearScreen: resq 1
.SetCursorPosition: resq 1
.EnableCursor: resq 1
.Mode: resq 1
endstruc

In that, the OutputString field holds the address of the UEFI function
which can be called to write a string of 16-bit chars to the screen. It
is passed

ECX = the STO table for the console (i.e. conout)
EDX = the string to print

Lo and behold, text appears! At least it does if one has everything
right. I can say more about that if anyone wants but for now I'll stop
here and not make this post any longer.

Feel free to add comments, questions and corrections.


--
James Harris

wolfgang kern

unread,
Nov 25, 2023, 1:13:58 AM11/25/23
to
On 24/11/2023 18:59, James Harris wrote:

> efi_main is:

> ;Called with x64 ms abi
> ;   RCX = image
> ;   RDX = systab

where to ??? address of this call ms abi is
[rcx + efi_stop.OutputString] ???


> global efi_main
> efi_main:
>
>   push rbp
>   mov rbp, rsp
>   sub rsp, 32
>   mov r10, rdi ;image
>   mov r11, rsi ;systab
>
>   lea rdx, [rel msg_hello]
>   mov rcx, [r11 + efi_systab.conout]
>   mov rax, [rcx + efi_stop.OutputString]

>   call rax
>
>   add rsp, 32
>   pop rbp
>   ret
>
> section .data
>
> msg_hello: dw __?utf16?__("Hello 64 UEFI..."), 13, 10, 0
...
> So pushing RBP will realign the stack. But that needs to be revisited.

yes, I'd try stack aligning from very start w/o using RBP at all,

may the call return any useful parameter on the stack or in REGs ?
or can we just ignore all of it.

copied from below:
> struc efi_stop ;UEFI simple text output protocol
> .Reset: resq 1
> .OutputString: resq 1
> .TestString: resq 1
> .QueryMode: resq 1
> .SetMode: resq 1
> .SetAttribute: resq 1
> .ClearScreen: resq 1
> .SetCursorPosition: resq 1
> .EnableCursor: resq 1
> .Mode: resq 1
> endstruc

how would this struct look in my notes: ?
I assume resq 1 mean 64 bit pointers

000 qq reset
008 qq OutputString
010 qq ...
...
048 qq mode

and how can we know the value for the call ?
is there a thunk table somewhere or windoze styled call by "name".

> In that, the OutputString field holds the address of the UEFI function

THAT'S the question: how to find these function addresses ?

> which can be called to write a string of 16-bit chars to the screen.
> It is passed
>
> ECX = the STO table for the console (i.e. conout)
> EDX = the string to print

> One thing UEFI gives the booted code is a pointer to the System Table.
> The table is documented in section 4. It starts with the following
> fields. (I included only as far as I needed.)

how. where and when will UEFI give me that?


> struc efi_systab ;UEFI system table
>   .hdr:      resb efi_hdr_size
>   .fvend:    resq 1 ;FirmwareVendor
>   .frev:     resd 1 ;FirmwareRevision
>              resd 1 ;padding
>   .coninh:   resq 1 ;ConsoleInHandle
>   .conin:    resq 1 ;ConIn
>   .conouth:  resq 1 ;ConsoleOutHandle
>   .conout:   resq 1 ;ConOut
> endstruc


> The header is

> struc efi_hdr ;Generic header
>   .Signature:    resq 1
>   .Revision:     resd 1
>   .HeaderSize:   resd 1
>   .CRC32:        resd 1
>                  resd 1  ;reserved
> endstruc

;can you please show me the above again in my notation
don't mind I already got your type cast style :)

> A note for anyone not familiar with C: where the spec in section 4.3.1 says
>
>   CHAR16                           *FirmwareVendor;
>   UINT32                           FirmwareRevision;
>
> whereas FirmwareRevision in the second line is uint32, as you might
> expect, the asterisk on the first line indicates that FirmwareVendor is
> a /pointer/ to the stated type, char16, and so in this case the field is
> 64-bit.

now I'm totally confused yet, CHAR16 means 64 bit ?
it seems it's just another 64 bit pointer.

> Going back to the code, the System Table's conout field is a pointer to
> a 'simple text output' (STO) table for the console, i.e. the screen at
> boot time. An STO table includes the following fields.
>
> struc efi_stop ;UEFI simple text output protocol
>   .Reset:                   resq 1
>   .OutputString:            resq 1
>   .TestString:              resq 1
>   .QueryMode:               resq 1
>   .SetMode:                 resq 1
>   .SetAttribute:            resq 1
>   .ClearScreen:             resq 1
>   .SetCursorPosition:       resq 1
>   .EnableCursor:            resq 1
>   .Mode:                    resq 1
> endstruc
>
> In that, the OutputString field holds the address of the UEFI function
> which can be called to write a string of 16-bit chars to the screen. It
> is passed
>
>   ECX = the STO table for the console (i.e. conout)
>   EDX = the string to print
>
> Lo and behold, text appears! At least it does if one has everything
> right. I can say more about that if anyone wants but for now I'll stop
> here and not make this post any longer.
>
> Feel free to add comments, questions and corrections.

thanks a lot, I now learned how to interpret your RESb/d/q :)
__
wolfgang

James Harris

unread,
Nov 25, 2023, 8:18:34 AM11/25/23
to
On 25/11/2023 06:13, wolfgang kern wrote:
> On 24/11/2023 18:59, James Harris wrote:
>
>> efi_main is:
>
>> ;Called with x64 ms abi
>> ;   RCX = image
>> ;   RDX = systab
>
> where to ???  address of this call ms abi is
> [rcx + efi_stop.OutputString] ???
>

No, take a look at the spec's section 2.3.4.1. Handoff State. It shows
that when UEFI calls an application it passes in the following.

Rcx - EFI_HANDLE
Rdx - EFI_SYSTEM_TABLE*
RSP - <return address>

IOW it passes us two parameters: an efi handle and something it calls
EFI_SYSTEM_TABLE*. The asterisk is C speak for 'pointer' so that second
parameter in RDX is a pointer to the efi system table.

The final part of the handoff state appears to mean only that RSP will
point to the return address.

>
>> global efi_main
>> efi_main:
>>
>>    push rbp
>>    mov rbp, rsp
>>    sub rsp, 32
>>    mov r10, rdi ;image
>>    mov r11, rsi ;systab
>>
>>    lea rdx, [rel msg_hello]
>>    mov rcx, [r11 + efi_systab.conout]
>>    mov rax, [rcx + efi_stop.OutputString]
>
>>    call rax
>>
>>    add rsp, 32
>>    pop rbp
>>    ret
>>
>> section .data
>>
>> msg_hello: dw __?utf16?__("Hello 64 UEFI..."), 13, 10, 0
> ...
>> So pushing RBP will realign the stack. But that needs to be revisited.
>
> yes, I'd try stack aligning from very start w/o using RBP at all,
>
> may the call return any useful parameter on the stack or in REGs ?
> or can we just ignore all of it.

Yes, have a read through section 2.3.4.2. Detailed Calling Conventions.
It includes "Return values that fix [which I guess is supposed to be
"fit"] into 64-bits are returned in the Rax register" etc.

>
> copied from below:
> > struc efi_stop ;UEFI simple text output protocol
> >    .Reset:                   resq 1
> >    .OutputString:            resq 1
> >    .TestString:              resq 1
> >    .QueryMode:               resq 1
> >    .SetMode:                 resq 1
> >    .SetAttribute:            resq 1
> >    .ClearScreen:             resq 1
> >    .SetCursorPosition:       resq 1
> >    .EnableCursor:            resq 1
> >    .Mode:                    resq 1
> > endstruc
>
> how would this struct look in my notes: ?
> I assume resq 1 mean 64 bit pointers

Not quite. All that that code is doing is reserving space, not saying
what should be in that space (pointer, integer, float etc). Nasm strucs
are documented in

https://www.nasm.us/xdoc/2.16.01/html/nasmdoc5.html#section-5.9.1

but perhaps more useful would be the sizes:

resb - reserve 1 byte
resw - reserve 1 word (2 bytes as far as Nasm is concerned)
resd - reserve 1 doubleword (4 bytes in Nasm)
resq - reserve 1 quadword (8 bytes in Nasm)

>
> 000 qq reset
> 008 qq OutputString
> 010 qq ...
> ...
> 048 qq mode
>
> and how can we know the value for the call ?
> is there a thunk table somewhere or windoze styled call by "name".

I don't know what Windows does but since posting yesterday I realised
that I should have changed my code a bit (added better comments and used
some different registers) and I had missed off code which you would need
which I didn't write but which is brought in by the link step. I'll show
the final executable's full disassembly below.

The new 'application' code is

efi_main:
push r13
push r12
push rbp
mov rbp, rsp
sub rsp, 32

;Save the supplied parameters in caller-save registers
mov r12, rdi ;image
mov r13, rsi ;systab

;Set up parms for text output
lea rdx, [rel msg_hello]
mov rcx, [r13 + efi_systab.conout]

;Make the call
mov rax, [rcx + efi_sto.OutputString]
call rax

add rsp, 32
pop rbp
pop r12
pop r13
ret

and the full disassembly which includes the above code and also the key
_start entry point is

$ objdump bin/x64cpu/bootx64b.efi -d -Mintel

bin/x64cpu/bootx64b.efi: file format pei-x86-64


Disassembly of section .text:

0000000000002000 <_text>:
2000: 41 55 push r13
2002: 41 54 push r12
2004: 55 push rbp
2005: 48 89 e5 mov rbp,rsp
2008: 48 83 ec 20 sub rsp,0x20
200c: 49 89 fc mov r12,rdi
200f: 49 89 f5 mov r13,rsi
2012: 48 8d 15 e7 1f 00 00 lea rdx,[rip+0x1fe7] # 4000
<_data>
2019: 49 8b 4d 40 mov rcx,QWORD PTR [r13+0x40]
201d: 48 8b 41 08 mov rax,QWORD PTR [rcx+0x8]
2021: ff d0 call rax
2023: 48 83 c4 20 add rsp,0x20
2027: 5d pop rbp
2028: 41 5c pop r12
202a: 41 5d pop r13
202c: c3 ret
202d: 0f 1f 00 nop DWORD PTR [rax]

0000000000002030 <_start>:
2030: 48 83 ec 08 sub rsp,0x8
2034: 51 push rcx
2035: 52 push rdx
2036: 48 8d 3d c3 df ff ff lea rdi,[rip+0xffffffffffffdfc3]
# 0 <_text-0x2000>
203d: 48 8d 35 bc 2f 00 00 lea rsi,[rip+0x2fbc] # 5000
<_DYNAMIC>
2044: 59 pop rcx
2045: 5a pop rdx
2046: 51 push rcx
2047: 52 push rdx
2048: e8 13 00 00 00 call 2060 <_relocate>
204d: 5f pop rdi
204e: 5e pop rsi
204f: e8 ac ff ff ff call 2000 <_text>
2054: 48 83 c4 08 add rsp,0x8

0000000000002058 <.exit>:
2058: c3 ret
2059: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]

0000000000002060 <_relocate>:
2060: f3 0f 1e fa endbr64
2064: 48 8b 06 mov rax,QWORD PTR [rsi]
2067: 48 85 c0 test rax,rax
206a: 74 7e je 20ea <_relocate+0x8a>
206c: 48 83 c6 08 add rsi,0x8
2070: 31 d2 xor edx,edx
2072: 45 31 c0 xor r8d,r8d
2075: 31 c9 xor ecx,ecx
2077: eb 1a jmp 2093 <_relocate+0x33>
2079: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
2080: 48 83 f8 07 cmp rax,0x7
2084: 74 72 je 20f8 <_relocate+0x98>
2086: 48 8b 46 08 mov rax,QWORD PTR [rsi+0x8]
208a: 48 83 c6 10 add rsi,0x10
208e: 48 85 c0 test rax,rax
2091: 74 1c je 20af <_relocate+0x4f>
2093: 48 83 f8 08 cmp rax,0x8
2097: 74 57 je 20f0 <_relocate+0x90>
2099: 48 83 f8 09 cmp rax,0x9
209d: 75 e1 jne 2080 <_relocate+0x20>
209f: 4c 8b 06 mov r8,QWORD PTR [rsi]
20a2: 48 8b 46 08 mov rax,QWORD PTR [rsi+0x8]
20a6: 48 83 c6 10 add rsi,0x10
20aa: 48 85 c0 test rax,rax
20ad: 75 e4 jne 2093 <_relocate+0x33>
20af: 48 89 d0 mov rax,rdx
20b2: 4c 09 c0 or rax,r8
20b5: 74 33 je 20ea <_relocate+0x8a>
20b7: 48 85 d2 test rdx,rdx
20ba: 74 44 je 2100 <_relocate+0xa0>
20bc: 4d 85 c0 test r8,r8
20bf: 74 3f je 2100 <_relocate+0xa0>
20c1: 48 85 c9 test rcx,rcx
20c4: 7e 24 jle 20ea <_relocate+0x8a>
20c6: 66 2e 0f 1f 84 00 00 cs nop WORD PTR [rax+rax*1+0x0]
20cd: 00 00 00
20d0: 83 7a 08 08 cmp DWORD PTR [rdx+0x8],0x8
20d4: 75 09 jne 20df <_relocate+0x7f>
20d6: 48 8b 02 mov rax,QWORD PTR [rdx]
20d9: 48 01 f8 add rax,rdi
20dc: 48 01 38 add QWORD PTR [rax],rdi
20df: 4c 29 c1 sub rcx,r8
20e2: 4c 01 c2 add rdx,r8
20e5: 48 85 c9 test rcx,rcx
20e8: 7f e6 jg 20d0 <_relocate+0x70>
20ea: 31 c0 xor eax,eax
20ec: c3 ret
20ed: 0f 1f 00 nop DWORD PTR [rax]
20f0: 48 8b 0e mov rcx,QWORD PTR [rsi]
20f3: eb 91 jmp 2086 <_relocate+0x26>
20f5: 0f 1f 00 nop DWORD PTR [rax]
20f8: 48 8b 16 mov rdx,QWORD PTR [rsi]
20fb: 48 01 fa add rdx,rdi
20fe: eb 86 jmp 2086 <_relocate+0x26>
2100: 48 b8 01 00 00 00 00 movabs rax,0x8000000000000001
2107: 00 00 80
210a: c3 ret
210b: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0]


Note that the code at the _start entry point for some reason calls
efi_main with the arguments in different registers.

Can we (or do we want to) remove the other code (which comes from
libraries at link time)? Maybe but I am aware of some caveats. We can
discuss them in subsequent posts, as needed. There's also more that you
might need to know in order to generate the PE file. But, again, that
needs another post.

>
> > In that, the OutputString field holds the address of the UEFI function
>
> THAT'S the question: how to find these function addresses ?
>
> > which can be called to write a string of 16-bit chars to the screen.
> > It is passed
> >
> >    ECX = the STO table for the console (i.e. conout)
> >    EDX = the string to print
>
>> One thing UEFI gives the booted code is a pointer to the System Table.
>> The table is documented in section 4. It starts with the following
>> fields. (I included only as far as I needed.)
>
> how. where and when will UEFI give me that?
>

Does the disassembly answer your remaining questions?


>
>> struc efi_systab ;UEFI system table
>>    .hdr:      resb efi_hdr_size
>>    .fvend:    resq 1 ;FirmwareVendor
>>    .frev:     resd 1 ;FirmwareRevision
>>               resd 1 ;padding
>>    .coninh:   resq 1 ;ConsoleInHandle
>>    .conin:    resq 1 ;ConIn
>>    .conouth:  resq 1 ;ConsoleOutHandle
>>    .conout:   resq 1 ;ConOut
>> endstruc
>
>
>> The header is
>
>> struc efi_hdr ;Generic header
>>    .Signature:    resq 1
>>    .Revision:     resd 1
>>    .HeaderSize:   resd 1
>>    .CRC32:        resd 1
>>                   resd 1  ;reserved
>> endstruc
>
> ;can you please show me the above again in my notation
> don't mind I already got your type cast style :)

See above. Hopefully I've answered that question now but please say if not.

>
>> A note for anyone not familiar with C: where the spec in section 4.3.1
>> says
>>
>>    CHAR16                           *FirmwareVendor;
>>    UINT32                           FirmwareRevision;
>>
>> whereas FirmwareRevision in the second line is uint32, as you might
>> expect, the asterisk on the first line indicates that FirmwareVendor
>> is a /pointer/ to the stated type, char16, and so in this case the
>> field is 64-bit.
>
> now I'm totally confused yet, CHAR16 means 64 bit ?
> it seems it's just another 64 bit pointer.

No, in C terms FirmwareVendor is a pointer - i.e. an address - and what
it points to is of type char16.
Those are not my terms but Nasm's. I didn't know you weren't familiar
with them but hopefully it's all now clear.


--
James Harris


wolfgang kern

unread,
Nov 25, 2023, 11:45:49 AM11/25/23
to
On 25/11/2023 14:18, James Harris wrote:
..
>> where to ???  address of this call ms abi is
>> [rcx + efi_stop.OutputString] ???

> No, take a look at the spec's section 2.3.4.1. Handoff State. It shows
> that when UEFI calls an application it passes in the following.

> Rcx - EFI_HANDLE
> Rdx - EFI_SYSTEM_TABLE*
> RSP - <return address>

I missed the very start of the whole story :)
when UEFI finds a valid file then it loads it and passes parameters:
In 32bit variant it comes on stack: [ESP+8] and [ESP].
Fine so far, with 64 bit mode: RCX and RDX.
But where would a Return go to ?
...
>> may the call return any useful parameter on the stack or in REGs ?
>> or can we just ignore all of it.

> Yes, have a read through section 2.3.4.2. Detailed Calling Conventions.
> It includes "Return values that fix [which I guess is supposed to be
> "fit"] into 64-bits are returned in the Rax register" etc.

> https://www.nasm.us/xdoc/2.16.01/html/nasmdoc5.html#section-5.9.1

> ...I'll show the final executable's full disassembly below.

I copied it away for a later compare with my thought solution.

...
> Note that the code at the _start entry point for some reason calls
> efi_main with the arguments in different registers.

> Can we (or do we want to) remove the other code (which comes from
> libraries at link time)? Maybe but I am aware of some caveats. We can
> discuss them in subsequent posts, as needed. There's also more that you
> might need to know in order to generate the PE file. But, again, that
> needs another post.

Yes, I'm not enough familiar with NASM so it may take me a few hours to
learn that too, or just get a clue of what all must be in the UEFI.bin.

UEFI comes with C-libraries ?
I'd delete them immediate :)

> Does the disassembly answer your remaining questions?

it may make me raise more questions later :)

>>> struc efi_systab ;UEFI system table
>>>    .hdr:      resb efi_hdr_size
>>>    .fvend:    resq 1 ;FirmwareVendor
>>>    .frev:     resd 1 ;FirmwareRevision
>>>               resd 1 ;padding
>>>    .coninh:   resq 1 ;ConsoleInHandle
>>>    .conin:    resq 1 ;ConIn
>>>    .conouth:  resq 1 ;ConsoleOutHandle
>>>    .conout:   resq 1 ;ConOut
>>> endstruc

>>> The header is
>>
>>> struc efi_hdr ;Generic header
>>>    .Signature:    resq 1
>>>    .Revision:     resd 1
>>>    .HeaderSize:   resd 1
>>>    .CRC32:        resd 1
>>>                   resd 1  ;reserved
>>> endstruc

I try to convert the above: (pointed to by RDX)
efi_systab:
000 dq ptr to efi_header
008 dq STR16ptr to FirmwareVendor ;UTF16
010 d FirmwareRevision
014 d 0000_0000
018 dq handle for ConsoleIN
020 dq ptr tp ConsoleIN
028 dq handle for ConsoleOut
030 dq ptr to ConsoleOUT
----------------------------
efi_header:
000 dq Signature
008 dq Revision
010 q Headersize (in bytes) wouldn't it just say 0000001c ?
014 q CRC32 ;of what ???
018 q reserved ....

>>> Going back to the code, the System Table's conout field is a pointer
>>> to a 'simple text output' (STO) table for the console, i.e. the
>>> screen at boot time. An STO table includes the following fields.

if this is pointed to by the ConsoleOUT aka conout above why has it a
different label yet ?

>>> struc efi_stop ;UEFI simple text output protocol
>>>    .Reset:                   resq 1
>>>    .OutputString:            resq 1
>>>    .TestString:              resq 1
>>>    .QueryMode:               resq 1
>>>    .SetMode:                 resq 1
>>>    .SetAttribute:            resq 1
>>>    .ClearScreen:             resq 1
>>>    .SetCursorPosition:       resq 1
>>>    .EnableCursor:            resq 1
>>>    .Mode:                    resq 1
>>> endstruc
>>>
>>> In that, the OutputString field holds the address of the UEFI
>>> function which can be called to write a string of 16-bit chars to the
>>> screen. It is passed
>>>
>>>    ECX = the STO table for the console (i.e. conout)
>>>    EDX = the string to print

so the above 10 pointers contain usable function-addresses ?

and to get the address of OutputString I just need to perform
mov rax,[[RDX+0028]+0010] (in KESYS ptr[ptr] syntax)
IOW:
MOV rax,[RDX+0028]
MOV rax,[RAX+0010]
followed by:
MOV EDX, mystring
call RAX

me think I'm now nearer to the matter and the docs became more
understandable for me yet.
__
wolfgang

Paul Edwards

unread,
Nov 25, 2023, 4:16:43 PM11/25/23
to
Hi James.

> I had missed off code which you would need
> which I didn't write but which is brought
> in by the link step. I'll show the final
> executable's full disassembly below.

You don't need this code if you produce
normal Windows PE executables with the
subsystem set to UEFI.

So depending on definitions, it would be
simplified if you used the appropriate tools.

mingw64 has what is required.

As does UCX64.

BFN. Paul.

James Harris

unread,
Nov 27, 2023, 10:31:07 AM11/27/23
to
On 25/11/2023 16:45, wolfgang kern wrote:
> On 25/11/2023 14:18, James Harris wrote:
> ..
>>> where to ???  address of this call ms abi is
>>> [rcx + efi_stop.OutputString] ???
>
>> No, take a look at the spec's section 2.3.4.1. Handoff State. It shows
>> that when UEFI calls an application it passes in the following.
>
>> Rcx - EFI_HANDLE
>> Rdx - EFI_SYSTEM_TABLE*
>> RSP - <return address>
>
> I missed the very start of the whole story :)
> when UEFI finds a valid file then it loads it and passes parameters:
> In 32bit variant it comes on stack: [ESP+8] and [ESP].
> Fine so far, with 64 bit mode: RCX and RDX.
> But where would a Return go to ?

AFAICT UEFI firmware is expected to have a 'boot manager' which knows
how to invoke one bootloader Application image after another until it
finds one which is willing to take control of the machine. Each
bootloader Application has to choose between two options:

Option 1: Go back to UEFI firmware. Two ways to do this: Either call
EFI_BOOT_SERVICES.Exit() (see sect 7.4.5) or return from efi_main.

Option 2: Take over the machine by calling ExitBootServices() and then,
most likely, pass control to an OS.

If we go back to the firmware then the boot manager could try a
different bootloader or drop to a CLI shell or present the user with a
TUI or GUI, etc. I guess that's configured on each machine.

For boot manager see section 3.

Status codes such as we might receive or we might pass back to EFI are
documented in appendix D.


> ...
>>> may the call return any useful parameter on the stack or in REGs ?
>>> or can we just ignore all of it.
>
>> Yes, have a read through section 2.3.4.2. Detailed Calling
>> Conventions. It includes "Return values that fix [which I guess is
>> supposed to be "fit"] into 64-bits are returned in the Rax register" etc.
>
>> https://www.nasm.us/xdoc/2.16.01/html/nasmdoc5.html#section-5.9.1
>
>> ...I'll show the final executable's full disassembly below.
>
> I copied it away for a later compare with my thought solution.
>
> ...
>> Note that the code at the _start entry point for some reason calls
>> efi_main with the arguments in different registers.
>
>> Can we (or do we want to) remove the other code (which comes from
>> libraries at link time)? Maybe but I am aware of some caveats. We can
>> discuss them in subsequent posts, as needed. There's also more that
>> you might need to know in order to generate the PE file. But, again,
>> that needs another post.
>
> Yes, I'm not enough familiar with NASM so it may take me a few hours to
> learn that too, or just get a clue of what all must be in the UEFI.bin.
>
> UEFI comes with C-libraries ?
> I'd delete them immediate :)

I agree. The reloc library code is not wanted.

That said, AISI I don't need it at present because my own code is
position-independent but if I ever need to have non-PIC code then some
form of PE-reloc code would be necessary.

>
>> Does the disassembly answer your remaining questions?
>
> it may make me raise more questions later :)

:-)
If the 3-digit numbers are offsets then not quite. If the header is 24
bytes then when struc efi_systab specifies

.hdr: resb efi_hdr_size

it is reserving 24 bytes at the start of the system table.

>
>>>> Going back to the code, the System Table's conout field is a pointer
>>>> to a 'simple text output' (STO) table for the console, i.e. the
>>>> screen at boot time. An STO table includes the following fields.
>
> if this is pointed to by the ConsoleOUT aka conout above why has it a
> different label yet ?

Not sure I understand the question but there's a common pattern in
calling UEFI firmware: that's to get an entry point from a structure and
then when calling the entry point pass it the address of the structure
that you got the entry point from. IOW, for structure S one would call

S->outputtext(S, "text")


>
>>>> struc efi_stop ;UEFI simple text output protocol
>>>>    .Reset:                   resq 1
>>>>    .OutputString:            resq 1
>>>>    .TestString:              resq 1
>>>>    .QueryMode:               resq 1
>>>>    .SetMode:                 resq 1
>>>>    .SetAttribute:            resq 1
>>>>    .ClearScreen:             resq 1
>>>>    .SetCursorPosition:       resq 1
>>>>    .EnableCursor:            resq 1
>>>>    .Mode:                    resq 1
>>>> endstruc
>>>>
>>>> In that, the OutputString field holds the address of the UEFI
>>>> function which can be called to write a string of 16-bit chars to
>>>> the screen. It is passed
>>>>
>>>>    ECX = the STO table for the console (i.e. conout)
>>>>    EDX = the string to print
>
> so the above 10 pointers contain usable function-addresses ?

I think the idea is that such structures can contain a mixture of
function addresses and data. For example, the .Mode field is a pointer
to data rather than a pointer to code.

Check the spec section 12.4.1 for details of the simple text output
structure.

>
> and to get the address of OutputString I just need to perform
> mov rax,[[RDX+0028]+0010]  (in KESYS ptr[ptr] syntax)
> IOW:
>   MOV rax,[RDX+0028]
>   MOV rax,[RAX+0010]
> followed by:
>   MOV EDX, mystring
>   call RAX

The first arg should be in RCX and it needs to be the address of the
conout table - something like:

;Set up parms for text output
lea rdx, [rel msg_hello]
mov rcx, [r13 + efi_systab.conout]

;Make the call
mov rax, [rcx + efi_sto.OutputString]
call rax

One thing to add: until you dismiss the EFI firmware you should follow
the ABI calling conventions exactly including saving any callee-save
registers etc or your code might work on some machines but not others.

Feel free to correct me if I've got something wrong or mention anything
you find out. This is a learning experience for me, too!


--
James Harris


James Harris

unread,
Nov 27, 2023, 10:44:32 AM11/27/23
to
On 25/11/2023 21:16, Paul Edwards wrote:
> Hi James.
>
>> I had missed off code which you would need
>> which I didn't write but which is brought
>> in by the link step. I'll show the final
>> executable's full disassembly below.

Hi Paul,

Any idea why your reply appears as a new thread?

>
> You don't need this code if you produce
> normal Windows PE executables with the
> subsystem set to UEFI.
>
> So depending on definitions, it would be
> simplified if you used the appropriate tools.
>
> mingw64 has what is required.
>
> As does UCX64.

Well, my development environment is Unix so I am not sure that either
would fit. More importantly, I think that I can already control what
goes in to the finished executable and have tried stripping out the
library code, it's just that there's an unresolved problem with the UEFI
firmware not liking the result.

Specifically, if I omit the library code then the UEFI firmware won't
run the .efi file. That may be because the file is no longer tagged as
relocatable but I'm not sure.

FWIW my current link step is

ld -o obj/x64cpu/bootx64b.so obj/x64cpu/bootx64b.o -nostdlib
-znocombreloc -T /usr/lib/elf_x86_64_efi.lds -shared -Bsymbolic
-L/usr/lib -l:crt0-efi-x86_64.o -lgnuefi -lefi

and that's converted to PE with

objcopy obj/x64cpu/bootx64b.so --subsystem=10 --target efi-app-x86_64 -j
.text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j
.reloc -j .eh_frame bin/x64cpu/bootx64b.efi

The line to run my UEFI code from a disk image is

qemu-system-x86_64 -bios /usr/share/qemu/OVMF.fd -drive
format=raw,file=/tmp/ehd.img -net none


--
James Harris


wolfgang kern

unread,
Nov 27, 2023, 5:43:31 PM11/27/23
to
On 27/11/2023 16:31, James Harris wrote:

> For boot manager see section 3.
OK.
> Status codes such as we might receive or we might pass back to EFI are
> documented in appendix D.
OK.
...
>> Yes, I'm not enough familiar with NASM so it may take me a few hours
>> to learn that too, or just get a clue of what all must be in the
>> UEFI.bin.

>> UEFI comes with C-libraries ?
>> I'd delete them immediate :)

> I agree. The reloc library code is not wanted.

> That said, AISI I don't need it at present because my own code is
> position-independent but if I ever need to have non-PIC code then some
> form of PE-reloc code would be necessary.

My code was/is always position independent w/o self-relocation needs
because I know what goes where by using my brain instead of guessing
what assembler/compiler might do.
So I use immediate constants rather than dynamic RIP addressing.

>>> Does the disassembly answer your remaining questions?
>> it may make me raise more questions later :)
> :-)
Questions may come soon :)

=========================================
=======================

> If the 3-digit numbers are offsets then not quite. If the header is 24
> bytes then when struc efi_systab specifies
>
>   .hdr:      resb efi_hdr_size
>
> it is reserving 24 bytes at the start of the system table.

I don't get that at all.
would you mind to correct my above translation in my format ?
...
> Feel free to correct me if I've got something wrong or mention anything
> you find out. This is a learning experience for me, too!

sing along: two blind mice... :)
coz my eyes became worse I need to zoom everything to 200%.
__
wolfgang

Paul Edwards

unread,
Nov 27, 2023, 7:42:13 PM11/27/23
to
Hi James.

> Any idea why your reply appears as a new thread?

Oh, that actually happened, did it? In google
groups my posts are appearing in the same thread
normally.

That initially surprised me, but then I thought
it was logical for situations where the reply is
not to anyone specific.

Bottom line is that I am using this crude program:

https://sourceforge.net/p/pdos/gitcode/ci/master/tree/src/pdpnntp.c

(which I wrote) since google groups became read-only.

I don't yet know how to construct a reply properly,
but even if I did, google groups isn't showing me
the raw headers (it used to), so I can't extract
the information I need.

I could get the raw headers via eternal september,
but that is more laborious. And I still don't know
the rules, regardless. I assume it's a simple matter
of getting the message-id from the original message
and then constructing some sort of in-reply-to
header line? If someone can confirm that, I'll try
to do a proper reply for you to confirm.

>> mingw64 has what is required.
>>
>> As does UCX64.

> Well, my development environment is Unix so I am not sure that either
> would fit. More importantly, I think that I can already control what
> goes in to the finished executable and have tried stripping out the
> library code, it's just that there's an unresolved problem with the UEFI
> firmware not liking the result.

Can you not run mingw under Wine to confirm that
you get a better result when you use standard
Windows calling convention and standard PE
executables?

I don't know if mingw64 can be built as a standard
Unix appication, but the tools in UCX64 are all
standard C90 applications except for cc64 which uses
a little bit of C99 (long long), so you need a compiler
with a little bit of C99 support (which you certainly
have), and then you can build native Linux tools that
produce proper PE executables instead of ELF-kludged.

And Wolfgang is probably using Windows so would probably
be better off going a route that doesn't involve the
Linux kludge.

Grant Taylor

unread,
Nov 27, 2023, 8:38:59 PM11/27/23
to
On 11/27/23 18:42, Paul Edwards wrote:
> Oh, that actually happened, did it? In google
> groups my posts are appearing in the same thread
> normally.

Yep, your message is appearing as a new thread.

> That initially surprised me, but then I thought
> it was logical for situations where the reply is
> not to anyone specific.

Messages are to the newsgroup(s). -- It's possible to send a single
message to multiple newsgroups in Usenet. I don't know if Google groups
allows that or not.

> (which I wrote) since google groups became read-only.

Oh ... Google Groups is far from read-only in general. I think there
are some newsgroups that are now read-only in Google Groups UI. But the
thousands of messages from Google Groups flooding other newsgroups (as
of a few days ago) are evidence of the read-write nature of Google
Groups Usenet gateway.

> I don't yet know how to construct a reply properly,
> but even if I did, google groups isn't showing me
> the raw headers (it used to), so I can't extract
> the information I need.

This is the 2nd or 3rd reference to Google Groups not making headers
available. That action really disappoints me. Yet more devolution of
Google Groups.

> I could get the raw headers via eternal september,
> but that is more laborious. And I still don't know
> the rules, regardless.

What rules are you thinking of / concerned about?

> I assume it's a simple matter
> of getting the message-id from the original message
> and then constructing some sort of in-reply-to
> header line? If someone can confirm that, I'll try
> to do a proper reply for you to confirm.

Yes.

References: <uk3d11$3vnan$1...@dont-email.me>

Where "<uk3d11$3vnan$1...@dont-email.me>" is the Message-ID: of the message
that I'm replying to.

References: is a Usenet construct while In-Reply-To: is more of an email
construct. That being said, it is quite common for messages to have both.

Both References: and In-Reply-To: include the Message-ID: of the message
that the reply is directly related to. One, I don't remember which, can
include more history like reply to a reply to a reply to a reply to an
original post type thing. -- Sorry, I can't be arsed to look up the
proper RFC for specifics.



--
Grant. . . .

wolfgang kern

unread,
Nov 27, 2023, 11:40:46 PM11/27/23
to
On 28/11/2023 01:42, Paul Edwards wrote:
...
>>> mingw64 has what is required.
...
> And Wolfgang is probably using Windows so would probably
> be better off going a route that doesn't involve the
> Linux kludge.

Yes, I use windoze for posting and games.
But for programming I use my own disassembling hex-edit
where only bare metal facts can happen at all.
I learned how to manually create short PE-files with that,
so all I now need to know is what all must be in efi.bin.
__
wolfgang

Paul Edwards

unread,
Nov 28, 2023, 12:46:25 AM11/28/23
to
Hi Grant.

>> Oh, that actually happened, did it? In google
>> groups my posts are appearing in the same thread
>> normally.

> Yep, your message is appearing as a new thread.

Ok, is this one properly threaded?

>> (which I wrote) since google groups became read-only.

> Oh ... Google Groups is far from read-only in general. I think there
> are some newsgroups that are now read-only in Google Groups UI. But the
> thousands of messages from Google Groups flooding other newsgroups (as
> of a few days ago) are evidence of the read-write nature of Google
> Groups Usenet gateway.

Ok, well, I can't click "compose" on comp.lang.c,
and in alt.os.development I can click "compose"
but last time I tried that I was asked to do a
captcha thing and then nothing happened. So I don't
want to waste my time fighting that anymore. I have
a news reader to write! And especially to get it to
fit into the Fidonet style, which is why there is an
"X-Comment-To".

>> I could get the raw headers via eternal september,
>> but that is more laborious. And I still don't know
>> the rules, regardless.

> What rules are you thinking of / concerned about?

The one you clarified - I am required to provide a
"References", but not a "In-Reply-To".

> Both References: and In-Reply-To: include the Message-ID: of the message
> that the reply is directly related to. One, I don't remember which, can
> include more history like reply to a reply to a reply to a reply to an
> original post type thing. -- Sorry, I can't be arsed to look up the
> proper RFC for specifics.

No problem, since I have no intention of implementing
it anyway. :-)

However, I do intend to, and I believe I have, done
the "References", so now that I know there is an issue,
and now that I know the rules, I will hopefully do the
right thing going forward.

BFN. Paul.

James Harris

unread,
Nov 28, 2023, 4:00:55 AM11/28/23
to
On 27/11/2023 22:43, wolfgang kern wrote:
> On 27/11/2023 16:31, James Harris wrote:

...

>>> UEFI comes with C-libraries ?
>>> I'd delete them immediate :)
>
>> I agree. The reloc library code is not wanted.
>
>> That said, AISI I don't need it at present because my own code is
>> position-independent but if I ever need to have non-PIC code then some
>> form of PE-reloc code would be necessary.
>
> My code was/is always position independent w/o self-relocation needs
> because I know what goes where by using my brain instead of guessing
> what assembler/compiler might do.
> So I use immediate constants rather than dynamic RIP addressing.

You'll still need to refer to your own data (such as a Hello message)
and will need the address of its first character. How would you get the
right address if you don't work it out relative to RIP? AIUI the UEFI
firmware makes no guarantees as to where it loads you code.

...
I'm not sure I understand enough of your format to do that but if the
first three digits are the offsets in decimal then I think the System
Table in 64-bit mode would begin something like

000 24-byte Hdr
024 8-byte FirmwareVendor
032 4-byte FirmwareRevision
036 4-byte (unnamed padding)
040 8-byte ConsoleInHandle
048 8-byte ConIn
056 8-byte ConsoleOutHandle
064 8-byte ConOut
072 8-byte StandardErrorHandle
etc

That's based on the header at 4.2 and the System Table at 4.3 and
noticing that I added padding to align the next field and finding that
according to 2.3.1 the EFI_HEADER type is void* which is a pointer which
would be in C terms a pointer to void (which one could think of as a
pointer to an undeclared type but all we need to know is that it's a
pointer, i.e. 8-bytes in 64-bit mode). Phew!

*IOW* there's a lot of assumptions and a bunch of manual transcription
in the offsets I've written so they may not all be correct but hopefully
the idea and the comments provide enough info for you to get a little
further forward. Feel free to tell me of any errors and do check out the
types in 2.3.1 remembering that in C declarations an asterisk means a
pointer so T* means a pointer to T.

You may prefer shorter names, as I did. I took the above field names
from the spec's description of the System Table (at 4.3).


--
James Harris


wolfgang kern

unread,
Nov 28, 2023, 6:26:22 AM11/28/23
to
On 28/11/2023 10:00, James Harris wrote:
> On 27/11/2023 22:43, wolfgang kern wrote:
>> On 27/11/2023 16:31, James Harris wrote:
>
> ...
>
>>>> UEFI comes with C-libraries ?
>>>> I'd delete them immediate :)
>>
>>> I agree. The reloc library code is not wanted.
>>
>>> That said, AISI I don't need it at present because my own code is
>>> position-independent but if I ever need to have non-PIC code then
>>> some form of PE-reloc code would be necessary.
>>
>> My code was/is always position independent w/o self-relocation needs
>> because I know what goes where by using my brain instead of guessing
>> what assembler/compiler might do.
>> So I use immediate constants rather than dynamic RIP addressing.
>
> You'll still need to refer to your own data (such as a Hello message)
> and will need the address of its first character. How would you get the
> right address if you don't work it out relative to RIP? AIUI the UEFI
> firmware makes no guarantees as to where it loads you code.

while with 32bit it can use CS override.
with 64bit I need a one time "where I am" like:
CALL next
next:
POP R15
THANKS, let my try again (I always use HEX unless otherwise noted)
my size cast for 1/2/4/8/16/32/64 bytes is b/w/q/dq/qq/dqq/qqq.
[I use Q for quad since 58 years, it was used on 4 gate TTLchips]

rfi_systab:
dec|hex|size|
00 000 dq Signature
08 008 dq Revision
16 010 q Headersize ;0000_001c yet
20 014 q CRC32 ;CHKSUM of header?
;...
24 018 dq 8 byte FirmwareVendor at:[systab+[systab+16]]
32  020 q 4-byte FirmwareRevision at:[systab+[systab+16]]+008
36  024 q 4-byte (unnamed padding)
40 028 dq 8-byte ConsoleInHandle at:[systab+[systab+16]]+010
48  030 dq 8-byte ConIn +018
56  038 dq 8-byte ConsoleOutHandle +020
64  040 dq 8-byte ConOut +028
72  048 dq 8-byte StandardErrorHandle +030
etc

> That's based on the header at 4.2 and the System Table at 4.3 and
> noticing that I added padding to align the next field and finding that
> according to 2.3.1 the EFI_HEADER type is void* which is a pointer which
> would be in C terms a pointer to void (which one could think of as a
> pointer to an undeclared type but all we need to know is that it's a
> pointer, i.e. 8-bytes in 64-bit mode). Phew!
>
> *IOW* there's a lot of assumptions and a bunch of manual transcription
> in the offsets I've written so they may not all be correct but hopefully
> the idea and the comments provide enough info for you to get a little
> further forward. Feel free to tell me of any errors and do check out the
> types in 2.3.1 remembering that in C declarations an asterisk means a
> pointer so T* means a pointer to T.

> You may prefer shorter names, as I did. I took the above field names
> from the spec's description of the System Table (at 4.3).

OK, names are good for docs. I never use any literals in my code,
a hexadecimal address is enough name for me.
thanks, I'm now one step closer to start an overall conversion.
let us hope that i live long enough to complete that book :)
__
wolfgang

Grant Taylor

unread,
Nov 28, 2023, 9:56:29 AM11/28/23
to
On 11/27/23 23:46, Paul Edwards wrote:
> Hi Grant.

Hi Paul,

> Ok, is this one properly threaded?

It appears to be.

> Ok, well, I can't click "compose" on comp.lang.c,
> and in alt.os.development I can click "compose"
> but last time I tried that I was asked to do a
> captcha thing and then nothing happened.

Sounds like specific groups may be read-only while other groups are
read-write.

> So I don't want to waste my time fighting that anymore.

Fair enough.

> I have
> a news reader to write! And especially to get it to
> fit into the Fidonet style, which is why there is an
> "X-Comment-To".

I'm not familiar with the X-Comment-To: header.

Though being a header starting with X- it's eXperimental. That being
said, a number of things abuse eXperimental as production.

> The one you clarified - I am required to provide a
> "References", but not a "In-Reply-To".

ACK

> No problem, since I have no intention of implementing
> it anyway. :-)

Fair.

N.B. save for supporting HTML, which is not required anyway, news and
email are quite similar. So if you write a client for one, you have
much of the client code for the other too. If you ever care.

> However, I do intend to, and I believe I have, done
> the "References", so now that I know there is an issue,
> and now that I know the rules, I will hopefully do the
> right thing going forward.

ACK

Learning at it's simplest form. You were unaware of something, you
became aware of it, and you became aware of how to overcome the issue.
<ASCII thumbs up>.

Scott Lurndal

unread,
Nov 28, 2023, 10:04:49 AM11/28/23
to
Paul Edwards <muta...@gmail.com> writes:
>Hi James.
>
>> Any idea why your reply appears as a new thread?
>
>Oh, that actually happened, did it? In google
>groups my posts are appearing in the same thread
>normally.
>
>That initially surprised me, but then I thought
>it was logical for situations where the reply is
>not to anyone specific.

>I don't yet know how to construct a reply properly,
>but even if I did, google groups isn't showing me
>the raw headers (it used to), so I can't extract
>the information I need.

You have an NNTP application, update it to use
grab the headers.

You need to provide a Message-ID: header, and
update the References: header to append the message
ID of the message you're replying to.

See the RFC for NNTP for details.

Paul Edwards

unread,
Nov 28, 2023, 4:08:47 PM11/28/23
to
Hi Scott.

> You have an NNTP application

You can euphemistically call it that.

> update it to use grab the headers.

I have that already. I just need to keep changing
the number until I find the right article.

The long-term plan is to ingest this into Msged,
a Fidonet application.

BTW, I was going to use UUCP on Eternal September
for that purpose. I don't yet know the protocol,
but I do get a userid/password prompt, and when I
enter my userid and password, Eternal September
terminates the connection. I tried some other userid
and passwords from examples in case this was not the
place you are supposed to enter your real userid
and password, but they didn't work either.

I do have a vague recollection that you need to
specifically request UUCP access, but I searched
and searched and couldn't find mention of such a
requirement anywhere.

Perhaps after entering the password I'm meant to
send something else very quickly or something,
and that's why it's terminating.

> You need to provide a Message-ID: header, and

Eternal September, running INN I believe, automatically
provides that for me. From the Fidonet-like side, I have
no interest in controlling the Message-ID, so that's great.

> update the References: header to append the message
> ID of the message you're replying to.

Ok, so it's supposed to be append, not replace. That's
probably what Grant was alluding to before.

But I probably can't support unlimited length
headers in Msged, so may need to strip that
down.

Another thing is that Fidonet allows paragraphs -
basically long lines. That culture will need to
change for interaction with Usenet too.

> See the RFC for NNTP for details.

Interestingly that (NNTP, RFC 977):

https://www.w3.org/Protocols/rfc977/rfc977.html

didn't have it.

But it was in USENET, RFC 850:

https://www.w3.org/Protocols/rfc850/rfc850.html

(aside to Grant - thanks for that info on the X-
being experimental - didn't know that)

BTW, it is fantastic to be back (since 1997) using
micro-emacs to write messages. But I really want
the Msged interface I was using back too. Now that
I have an operating system to run it under. Before
I was using OS/2.

BFN. Paul.

Scott Lurndal

unread,
Nov 28, 2023, 4:29:19 PM11/28/23
to
Paul Edwards <muta...@gmail.com> writes:
>Hi Scott.
>
>> You have an NNTP application
>
>You can euphemistically call it that.
>
>> update it to use grab the headers.
>
>I have that already. I just need to keep changing
>the number until I find the right article.

I assume you're familiar with RFC 3977.

Use the OVER command to get the the message-id
header and References header for the current article.

Then use XHDR (or the newer HDR/LIST HEADERS) commands.



>Ok, so it's supposed to be append, not replace. That's
>probably what Grant was alluding to before.

Prepend, not append, I believe., e.g. here are the
headers for your post:

Path: not-for-mail
From: Paul Edwards <muta...@gmail.com>
Newsgroups: alt.os.development
Subject: Re: UEFI boot basics
Date: Tue, 28 Nov 2023 21:08:44 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 74
Message-ID: <uk5ksr$e7da$1...@dont-email.me>
References: <uk3d11$3vnan$1...@dont-email.me> <ikn9N.30033$rx%7.1...@fx47.iad>
Injection-Date: Tue, 28 Nov 2023 21:08:44 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="35c6e3a925efc030fe95aa1921b6c7ba";
logging-data="466346"; mail-complaints-to="ab...@eternal-september.org"; posting-account="U2FsdGVkX1/1qQ9OGF3agDIe8Ha3B+ckhY8dpEnMF30="
Cancel-Lock: sha1:Pj1/OA2hggwl6/+qaOjw3zW/O8E=
X-Received-Bytes: 3143

>
>But I probably can't support unlimited length
>headers in Msged, so may need to strip that
>down.
>
>Another thing is that Fidonet allows paragraphs -
>basically long lines. That culture will need to
>change for interaction with Usenet too.
>
>> See the RFC for NNTP for details.
>
>Interestingly that (NNTP, RFC 977):
>
>https://www.w3.org/Protocols/rfc977/rfc977.html
>
>didn't have it.

try 3977.

Paul Edwards

unread,
Nov 28, 2023, 7:52:21 PM11/28/23
to
Hi Scott.

>> I have that already. I just need to keep changing
>> the number until I find the right article.

> I assume you're familiar with RFC 3977.

Incorrect assumption.

> Use the OVER command to get the the message-id
> header and References header for the current article.

> Then use XHDR (or the newer HDR/LIST HEADERS) commands.

Any such thing needs to be written. So far it
hasn't been written. The software in question is here:

https://sourceforge.net/p/pdos/gitcode/ci/master/tree/src/pdpnntp.c

My priority is to get that working on z/PDOS,
not add more bells and whistles to the PDOS/386 version.

So until then, the software requires me to choose a
single number. And I update a .bat file to specify
that number. And then if I get the number wrong, I
poweroff and do a fresh connection to Eternal September
(using qemu to point COM1: to there).

>> Ok, so it's supposed to be append, not replace. That's
>> probably what Grant was alluding to before.

> Prepend, not append, I believe., e.g. here are the
> headers for your post:

You showed the message from me as:

Message-ID: <uk5ksr$e7da$1...@dont-email.me>
References: <uk3d11$3vnan$1...@dont-email.me> <ikn9N.30033$rx%7.1...@fx47.iad>

The one from you just now is:

Message-ID: <LYs9N.153256$Ee89....@fx17.iad>
References: <uk3d11$3vnan$1...@dont-email.me> <ikn9N.30033$rx%7.1...@fx47.iad> ...
<uk5ksr$e7da$1...@dont-email.me>

ie the uk5 message-id that you got from me has clearly been
APPENDED to the references that you received from me.

And that is in accordance with what the spec says:

https://www.w3.org/Protocols/rfc850/rfc850.html

If the original article does have a References line, the
followup article should have a References line containing
the text of the original References line, a blank, and
the message ID of the original article.

I don't think it is reasonable for small systems
to support infinitely-long lines though. I'll probably
violate the spec and just have a single reference.

>> Interestingly that (NNTP, RFC 977):
>>
>> https://www.w3.org/Protocols/rfc977/rfc977.html
>
>> didn't have it.

> try 3977.

Nope, "References" isn't documented there either.

What's wrong with the reference (850) I already gave?

BFN. Paul.

wolfgang kern

unread,
Nov 28, 2023, 10:03:52 PM11/28/23
to
On 29/11/2023 01:52, Paul Edwards wrote:
...

> What's wrong with the reference (850) I already gave?

w/o the complete reference path you mess up our threads by showing
several topics with the same RE:wording.
stop playing if you don't want to become reported to ES and google.
use any test-group with your use-net attempts until ready.
__
wolfgang

Grant Taylor

unread,
Nov 29, 2023, 12:00:30 AM11/29/23
to
On 11/28/23 21:03, wolfgang kern wrote:
> w/o the complete reference path you mess up our threads by showing
> several topics with the same RE:wording.

That's contrary to my understanding.

References MUST reflect the Message-ID: of the message you are replying to.

References SHOULD also reflect any parent Message-ID:s too.

N.B. MUST vs SHOULD

N.B. There is an effective upper limit on the (logical) line length of
the References: header. As such, once you get far enough in, the older
Message-ID:s fall off the end.

wolfgang kern

unread,
Nov 29, 2023, 1:31:19 AM11/29/23
to
yeah, I meant _complete_ in terms of not missing what's required.
I didn't say "all of it".
__
wolfgang

James Harris

unread,
Nov 29, 2023, 3:52:18 AM11/29/23
to
On 28/11/2023 11:26, wolfgang kern wrote:
> On 28/11/2023 10:00, James Harris wrote:
>> On 27/11/2023 22:43, wolfgang kern wrote:
>>> On 27/11/2023 16:31, James Harris wrote:

...

>>>> I agree. The reloc library code is not wanted.
>>>
>>>> That said, AISI I don't need it at present because my own code is
>>>> position-independent but if I ever need to have non-PIC code then
>>>> some form of PE-reloc code would be necessary.
>>>
>>> My code was/is always position independent w/o self-relocation needs
>>> because I know what goes where by using my brain instead of guessing
>>> what assembler/compiler might do.
>>> So I use immediate constants rather than dynamic RIP addressing.
>>
>> You'll still need to refer to your own data (such as a Hello message)
>> and will need the address of its first character. How would you get
>> the right address if you don't work it out relative to RIP? AIUI the
>> UEFI firmware makes no guarantees as to where it loads you code.
>
> while with 32bit it can use CS override.
> with 64bit I need a one time "where I am" like:
> CALL next
> next:
> POP R15

A few points:

1. x86 32-bit UEFI boot may not be widely supported. You may be better
to be able to boot a 64-bit UEFI OS loader and switch to 32-bit mode if
you want to start a 32-bit OS.

2. If UEFI load addresses aren't guaranteed then consider these scenarios:

a) Code at 1000, data at 1400
b) Code at 2000, data at 2400

What you need is data /relative to code/. Having a CS override wouldn't
help if you don't know where your code and data will be relative to CS.

3) If writing a 32-bit UEFI OS loader you could use call/pop to get data
address relative to wherever the code happens to have been loaded.

4) In x64 you don't need call/pop but can use RIP-relative references as in

lea rdx, [rel msg_hello]

for which the hex is

48 8d 15 e7 1f 00 00 lea rdx,[rip+0x1fe7]

5) The choices are to write PIC code or use relocation but bear in mind
that UEFI firmware has to see your final PE file as something it is
willing to load and execute so it might expect some flags or indicators
to tell it that the file is PIC or, failing that, that it comes with a
relocation section. UEFI is a lot more fussy than BIOS as to what it
will hand control to.


--
James Harris


wolfgang kern

unread,
Nov 30, 2023, 1:35:44 AM11/30/23
to
On 29/11/2023 09:49, James Harris wrote:
> On 28/11/2023 11:26, wolfgang kern wrote:
...

>>> How would you get the right address if you don't work it out relative to RIP? AIUI the UEFI firmware makes no guarantees as to where it loads you code.

>> while with 32bit it can use CS override.
>> with 64bit I need a one time "where I am" like:
>> CALL next
>> next:
>> POP R15

> A few points:
>
> 1. x86 32-bit UEFI boot may not be widely supported. You may be better
> to be able to boot a 64-bit UEFI OS loader and switch to 32-bit mode if
> you want to start a 32-bit OS.
>
> 2. If UEFI load addresses aren't guaranteed then consider these scenarios:
>
> a) Code at 1000, data at 1400
> b) Code at 2000, data at 2400

I cannot believe that it may randomly load to different locations.
there must be some rule ie: dependent on media sector size.

> What you need is data /relative to code/. Having a CS override wouldn't
> help if you don't know where your code and data will be relative to CS.

when I write the file I know the data offset from within the code.
yours is 0x0400 for the text test. Mine will be much larger (>64K).

> 3) If writing a 32-bit UEFI OS loader you could use call/pop to get data
> address relative to wherever the code happens to have been loaded.
>
> 4) In x64 you don't need call/pop but can use RIP-relative references as in
>
>   lea rdx, [rel msg_hello]
>
> for which the hex is
>
>   48 8d 15 e7 1f 00 00     lea    rdx,[rip+0x1fe7]

OK I see it, but it is limited to 64k distance (same as in 32bit).

my one time self relocation used on start of several temporary dynamic
loaded modules (all static stuff is at fixed offsets as part of OS).

E8 0000_0000 CALL next
5A POP ESI
... adjust with known offsets

How would a 64bit version with larger than 64k code size look like?


> 5) The choices are to write PIC code or use relocation but bear in mind
> that UEFI firmware has to see your final PE file as something it is
> willing to load and execute so it might expect some flags or indicators
> to tell it that the file is PIC or, failing that, that it comes with a
> relocation section.

you mean UEFI will disassemble my code before loading it ?
we need to learn what exactly is required to make UEFI load and execute.

> UEFI is a lot more fussy than BIOS as to what it will hand control to.

Oh yeah, that was the reason for I stopped all business with KESYS.

BTW, you have a working text test?
can you read out a few registers and print the values?
it would be interesting what we get on start, especially RSP.
__
wolfgang

James Harris

unread,
Nov 30, 2023, 5:30:22 AM11/30/23
to
On 30/11/2023 06:35, wolfgang kern wrote:
> On 29/11/2023 09:49, James Harris wrote:
>> On 28/11/2023 11:26, wolfgang kern wrote:
> ...
>
>>>> How would you get the right address if you don't work it out
>>>> relative to RIP? AIUI the UEFI firmware makes no guarantees as to
>>>> where it loads you code.
>
>>> while with 32bit it can use CS override.
>>> with 64bit I need a one time "where I am" like:
>>> CALL next
>>> next:
>>> POP R15
>
>> A few points:
>>
>> 1. x86 32-bit UEFI boot may not be widely supported. You may be better
>> to be able to boot a 64-bit UEFI OS loader and switch to 32-bit mode
>> if you want to start a 32-bit OS.
>>
>> 2. If UEFI load addresses aren't guaranteed then consider these
>> scenarios:
>>
>> a) Code at 1000, data at 1400
>> b) Code at 2000, data at 2400
>
> I cannot believe that it may randomly load to different locations.

Why not? A UEFI app (such as a bootloader) is just an app as far as UEFI
is concerned. Where it gets loaded is not specified as it was with BIOS.
There's no simple 0x7c00 any more! The actual location of one's
bootloader will likely depend on who wrote the firmware, what /version/
of the firmware is being used, what drivers have been loaded beforehand,
what happened on the machine before it loaded our bootloader, etc.

> there must be some rule ie: dependent on media sector size.
>
>> What you need is data /relative to code/. Having a CS override
>> wouldn't help if you don't know where your code and data will be
>> relative to CS.
>
> when I write the file I know the data offset from within the code.
> yours is 0x0400 for the text test. Mine will be much larger (>64K).
>
>> 3) If writing a 32-bit UEFI OS loader you could use call/pop to get
>> data address relative to wherever the code happens to have been loaded.
>>
>> 4) In x64 you don't need call/pop but can use RIP-relative references
>> as in
>>
>>    lea rdx, [rel msg_hello]
>>
>> for which the hex is
>>
>>    48 8d 15 e7 1f 00 00     lea    rdx,[rip+0x1fe7]
>
> OK I see it, but it is limited to 64k distance (same as in 32bit).

Are you sure it's not +/- 2G? (Those zeroes...!)

>
> my one time self relocation used on start of several temporary dynamic
> loaded modules (all static stuff is at fixed offsets as part of OS).
>
> E8 0000_0000  CALL next
> 5A            POP  ESI
> ...           adjust with known offsets

That's fine, too, especially if used only once and not in tight nested
loops.

>
> How would a 64bit version with larger than 64k code size look like?

As I say, +/- 2G should be available.

>
>
>> 5) The choices are to write PIC code or use relocation but bear in
>> mind that UEFI firmware has to see your final PE file as something it
>> is willing to load and execute so it might expect some flags or
>> indicators to tell it that the file is PIC or, failing that, that it
>> comes with a relocation section.
>
> you mean UEFI will disassemble my code before loading it ?

:-)

No, but remember that a bootloader has to be in PE format and such a
format has descriptive fields in its headers. The firmware will
naturally only load files if it likes what it sees in the headers.

> we need to learn what exactly is required to make UEFI load and execute.

That has to come from the spec because there are many implementations -
both present and future.

>
>> UEFI is a lot more fussy than BIOS as to what it will hand control to.
>
> Oh yeah, that was the reason for I stopped all business with KESYS.
>
> BTW, you have a working text test?
> can you read out a few registers and print the values?
> it would be interesting what we get on start, especially RSP.

I have working text output but not number output in Asm. I could add it
but it doesn't seem useful for this as the contents of registers which
are not mentioned in the spec are unlikely to be consistent, AFIACS.


--
James Harris


wolfgang kern

unread,
Nov 30, 2023, 10:23:36 AM11/30/23
to
On 30/11/2023 11:30, James Harris wrote:
...
>>> a) Code at 1000, data at 1400
>>> b) Code at 2000, data at 2400

>> I cannot believe that it may randomly load to different locations.

> Why not? A UEFI app (such as a bootloader) is just an app as far as UEFI
> is concerned. Where it gets loaded is not specified as it was with BIOS.

Isn't the first thing it loads (or tries to) a file from the FAT32 root
directory with a certain name like "efi.bin" ?

> There's no simple 0x7c00 any more! The actual location of one's
> bootloader will likely depend on who wrote the firmware, what /version/
> of the firmware is being used, what drivers have been loaded beforehand,
> what happened on the machine before it loaded our bootloader, etc.

Yes, there should be something like HW detection, GDT/IDT, USB and VESA
stuff already mounted for the boot [ROM BIOS did that as well].

...
>>>    48 8d 15 e7 1f 00 00     lea    rdx,[rip+0x1fe7]
>> OK I see it, but it is limited to 64k distance (same as in 32bit).
> Are you sure it's not +/- 2G? (Those zeroes...!)

yeah got me :) I checked on my disassembler and it tells this four bytes
are signed relative to following instruction (same as jump near/short),

>> my one time self relocation used on start of several temporary dynamic
>> loaded modules (all static stuff is at fixed offsets as part of OS).

>> E8 0000_0000  CALL next
>> 5E            POP  ESI
>> ...           adjust with known offsets

> That's fine, too, especially if used only once and not in tight nested
> loops.

it should work almost equal in 64bit:
E8 0000_0000 CALL next ;sign-extended to 64 bit relative to L1
L1: 5E POP RSI ;get 64bit address of L1

>>> 5) The choices are to write PIC code or use relocation but bear in
>>> mind that UEFI firmware has to see your final PE file as something it
>>> is willing to load and execute so it might expect some flags or
>>> indicators to tell it that the file is PIC or, failing that, that it
>>> comes with a relocation section.

I think relocation requirement is found in the header of an PE,
so if non is mentioned there UEFI should know how to act.

>> you mean UEFI will disassemble my code before loading it ?
> :-)
> No, but remember that a bootloader has to be in PE format and such a
> format has descriptive fields in its headers. The firmware will
> naturally only load files if it likes what it sees in the headers.

you mean UEFI insists to have relocation ? what for ?

I have a copy from Herbert's shortest possible PE. I'll read it again.

>> we need to learn what exactly is required to make UEFI load and execute.

> That has to come from the spec because there are many implementations -
> both present and future.

>>> UEFI is a lot more fussy than BIOS as to what it will hand control to.
>> Oh yeah, that was the reason for I stopped all business with KESYS.

>> BTW, you have a working text test?
>> can you read out a few registers and print the values?
>> it would be interesting what we get on start, especially RSP.

> I have working text output but not number output in Asm. I could add it
> but it doesn't seem useful for this as the contents of registers which
> are not mentioned in the spec are unlikely to be consistent, AFIACS.

I remember back then when DOS once had similar issues, meanwhile start
conditions and reg-values are well documented and reliable (hugi comp).

I think UEFI will also either behave standardized or vanish soon.
what's missing on this matter is non C-styled detailed information.

OK so far I'll work on that after I assembled my new PC with parts
bought today [this may take a while].
__
wolfgang

Scott Lurndal

unread,
Nov 30, 2023, 10:41:13 AM11/30/23
to
Have you examined the UEFI source code? Most vendors base their implementation
on Tianocore.

https://github.com/tianocore

https://uefi.org/

Scott Lurndal

unread,
Nov 30, 2023, 12:06:39 PM11/30/23
to
UEFI -is already- standardized, and will never 'vanish'.

The alternative used by non-PC systems is generally uboot.

https://docs.u-boot.org/en/latest/


Paul Edwards

unread,
Nov 30, 2023, 4:06:25 PM11/30/23
to
>> What's wrong with the reference (850) I already gave?

> w/o the complete reference path

1. You quoted a reference to an RFC. There is nothing
wrong with the RFC 850 I gave.

2. As you have already conceded, the complete reference
is not required (apparently - although I didn't see that
in the old RFC). Just the most recent message-id. BTW,
I just found out that the References line isn't one huge
long line. There are two per line, but presumably that is
flexible. So the References going out in this message is
going to be:

References: <uk3d11$3vnan$1...@dont-email.me> <ikn9N.30033$rx%7.1...@fx47.iad>
<uk5ksr$e7da$1...@dont-email.me> <LYs9N.153256$Ee89....@fx17.iad>
<uk6200$g1fe$1...@dont-email.me> <uk69m9$kt41$1...@dont-email.me>

I think I previously sent one with 4 in one line,
which may have exceeded some limit, but I was
replying to one with 3 in one line that exceeded
80 characters itself.

3. All my messages (including the one you replied to)
have the complete References already. I haven't once
sent out a partial References. I previously
wasn't sending out ANY References, but I fixed that as soon
as someone told me what the technical issue was.

> you mess up our threads by showing
> several topics with the same RE:wording.

That may happen on your news reader, but it doesn't
happen on Google Groups, so I wasn't aware there was
a problem until someone alerted me, and then I fixed
it as soon as someone told me what I was doing wrong.

> stop playing

I'm not "playing". I have always posted what I believed
were technically accurate messages.

> if you don't want to become reported to ES and google.

I don't see how I can be reported to google when I'm
not posting anything via google (because I can't anymore).

And although there is nothing preventing someone from
reporting me to ES, I think that is a very lousy thing
to do - trying to get me (potentially) banned because of
a threading issue. Also it would be a pretty harsh
judgement - this is an "alt" group. There are no rules
and no moderator. That's why Rick was able to post all
that religious stuff. Your only choice was to block him
at an individual level. In this case, you're assuming
that there is a rule that I can't start a new thread
with the same subject, and that ES will agree. See above
about "no rules". But I agree they may decide it's a
rule/non-rule violation regardless.

> use any test-group with your use-net attempts until ready.

I already did exactly that. I posted to an eternal september
test group. I was able to retrieve that message. It looked
fine to me (ES added a stack of header lines to my original).
Then I made a new post in alt.os.development.
That then appeared in google groups (which I can still read),
and also looked fine.

It was only later when I was replying to messages that an
issue (not visible to me via google groups) was discovered
in my software/procedure, and it was fixed in hours.

And you're already ready to report me to the authorities
as your initial "go to" solution? My goodness.

Grant Taylor

unread,
Nov 30, 2023, 7:55:19 PM11/30/23
to
On 11/30/23 15:06, Paul Edwards wrote:
> I just found out that the References line isn't one huge
> long line.

Not necessarily.

> There are two per line, but presumably that is
> flexible. So the References going out in this message is
> going to be:
>
> References: <uk3d11$3vnan$1...@dont-email.me> <ikn9N.30033$rx%7.1...@fx47.iad>
> <uk5ksr$e7da$1...@dont-email.me> <LYs9N.153256$Ee89....@fx17.iad>
> <uk6200$g1fe$1...@dont-email.me> <uk69m9$kt41$1...@dont-email.me>

From memory -- I'm not finding and reading an RFC for this -- there are
basically three lengths that come into play.

- what will fit in a ""standard window, generally considered to be
72-78 characters.
- a physical line length
- a logical line length

I believe that the physical line length (for email, which news articles
have significant overlap with) is 1000 characters, including trailing
<CR><LF> so effectively 998 characters on the line.

I believe that theoretically the logical, unfolded / unwrapped line is
unlimited. However going beyond the physical line length of ~1k tends
to tickle bugs in things like there is no tomorrow.

Many things use a physical line length of < 80 characters and a logical
line length of < 1000 characters.

I say this to say that you could put all references and the header on
one line as long as it's less than the physical line length, even if
it's longer than the ~80 characters people consider to be good netiquette.

> I think I previously sent one with 4 in one line,
> which may have exceeded some limit, but I was
> replying to one with 3 in one line that exceeded
> 80 characters itself.

Four entries and a References header should have hardly scratched the
physical line length unless they were obscenely long Message-IDs. That
being said, they may have crossed the netiquette suggested 80 characters.

N.B. the 80 characters goes back to fixed with terminals and is IMHO
outdated. I now use terminals at least 132 characters wide and
frequently widen them. But the idea of the netiquette is to avoid
inconveniencing others and be considerate of their terminals by making
small changes in what you do.

> That may happen on your news reader, but it doesn't
> happen on Google Groups, so I wasn't aware there was
> a problem until someone alerted me, and then I fixed
> it as soon as someone told me what I was doing wrong.

There is another form of threading contrary to the References: /
In-Reply-To: header and that's based on clients trying to be smart and
guess based on the Subject: header and date and maybe the opening quote
in the body. This is pseudo threading that works part of the time and
fails miserably other parts of the time.

> I'm not "playing". I have always posted what I believed
> were technically accurate messages.

I trust that you are sending messages in good faith. However there is
one small nitpick that may be considered playing by some. (More below.)

> I don't see how I can be reported to google when I'm
> not posting anything via google (because I can't anymore).

The only thing that I see that might be not 100% pure / innocent is
testing things about message threading in the alt.os.development
newsgroup. Usenet message threading may not be on topic in /this/
newsgroup.

That being said, so what.

Your /off/ /topic/ content became off topic as part of a reply / comment
/ complaint to an on topic post. You carried the conversation forward
in situ.

I'm continuing to carry your conversation forward in situ as well.

We are having polite, civil, productive conversation. Even if it's not
100% on topic for /this/ /newsgroup/.

Other than that, I don't see anything to complain about.

> And although there is nothing preventing someone from
> reporting me to ES, I think that is a very lousy thing
> to do - trying to get me (potentially) banned because of
> a threading issue. Also it would be a pretty harsh
> judgement - this is an "alt" group. There are no rules
> and no moderator.

I'd be flabbergasted if you got anything more than a "please stay on
topic in $NEWSGROUP" type comment. Maybe if you repeatedly did it and
had multiple complaints and multiple such comments. But then, it would
not be a surprise to you.

> That's why Rick was able to post all
> that religious stuff. Your only choice was to block him
> at an individual level. In this case, you're assuming
> that there is a rule that I can't start a new thread
> with the same subject, and that ES will agree. See above
> about "no rules". But I agree they may decide it's a
> rule/non-rule violation regardless.
I also suspect that the E-S newsmaster has their hands full dealing with
actual spam from Google Groups.

I suspect that they would take one look at this and either ask "why am I
being bothered with this" or send you a message saying "please try to
stay on topic".

If anything, the comment about reporting you is more likely meant to
intimidate you.

> I already did exactly that. I posted to an eternal september
> test group. I was able to retrieve that message. It looked
> fine to me (ES added a stack of header lines to my original).
> Then I made a new post in alt.os.development.
> That then appeared in google groups (which I can still read),
> and also looked fine.
>
> It was only later when I was replying to messages that an
> issue (not visible to me via google groups) was discovered
> in my software/procedure, and it was fixed in hours.

I believe that Google Groups supports subject based threading.

> And you're already ready to report me to the authorities
> as your initial "go to" solution? My goodness.

Chuckle.

wolfgang kern

unread,
Dec 1, 2023, 1:25:14 AM12/1/23
to
On 30/11/2023 16:41, Scott Lurndal wrote:
...
>> I think UEFI will also either behave standardized or vanish soon.
>> what's missing on this matter is non C-styled detailed information.

> Have you examined the UEFI source code?

it's in C so it's useless for bare metal machine code programmers.

> Most vendors base their implementation
> on Tianocore.

> https://github.com/tianocore

thx, but I can't find anything useful for me there.

> https://uefi.org/

I have this one pinned to my taskbar... and I started translation into
hex-dump/RBIL-styled info already.
__
wolfgang

wolfgang kern

unread,
Dec 1, 2023, 1:30:54 AM12/1/23
to
On 30/11/2023 22:06, Paul Edwards wrote:
...
> And you're already ready to report me to the authorities
> as your initial "go to" solution? My goodness.

not me of course, it was just a brief warning.
__
wolfgang

James Harris

unread,
Dec 1, 2023, 8:24:09 AM12/1/23
to
On 30/11/2023 15:23, wolfgang kern wrote:
> On 30/11/2023 11:30, James Harris wrote:
> ...
>>>> a) Code at 1000, data at 1400
>>>> b) Code at 2000, data at 2400
>
>>> I cannot believe that it may randomly load to different locations.
>
>> Why not? A UEFI app (such as a bootloader) is just an app as far as
>> UEFI is concerned. Where it gets loaded is not specified as it was
>> with BIOS.
>
> Isn't the first thing it loads (or tries to) a file from the FAT32 root
> directory with a certain name like "efi.bin" ?

We were talking about /where/ UEFI loads the PE file. And you've kept
that prior discussion in. So the change to /what/ UEFI loads is unexpected.

But on the topic of what gets loaded ... all I can say is I don't know!
I presume each machine can be configured with a list of things to try.
Just like a BIOS can be configured to look for a floppy, an optical
drive, then the first hard disk, or similar, I believe a UEFI machine
can be configured to try a series of potentially bootable media and
files until it gets to one which works.

That said, there are some standard locations, most notably

/efi/boot/

Files in there called

bootARCH.efi

are meant to be bootable for the specified architecture. ARCH could be
such as ia32 or x64 (and yes, 3-char architecture names are OK).

I have been testing with qemu. No idea how to configure a boot list on
it but by default it will load either

/efi/boot/bootx64.efi

or

/startup.nsh

where the latter is a series of textual commands. startup.nsh is akin to
autoexec.bat.

>
>> There's no simple 0x7c00 any more! The actual location of one's
>> bootloader will likely depend on who wrote the firmware, what
>> /version/ of the firmware is being used, what drivers have been loaded
>> beforehand, what happened on the machine before it loaded our
>> bootloader, etc.
>
> Yes, there should be something like HW detection, GDT/IDT, USB and VESA
> stuff already mounted for the boot [ROM BIOS did that as well].

...

>>>> 5) The choices are to write PIC code or use relocation but bear in
>>>> mind that UEFI firmware has to see your final PE file as something
>>>> it is willing to load and execute so it might expect some flags or
>>>> indicators to tell it that the file is PIC or, failing that, that it
>>>> comes with a relocation section.
>
> I think relocation requirement is found in the header of an PE,
> so if non is mentioned there UEFI should know how to act.

Note, though, that in the previously posted disassembly the PE file
appeared to do its own relocation.

I think the services UEFI might use to load PE files are

EFI_BOOT_SERVICES.LoadImage
EFI_BOOT_SERVICES.StartImage

but from a quick scan the standards don't seem to say what either of
them does about relocation. Probably nothing, would be my guess.

>
>>> you mean UEFI will disassemble my code before loading it ?
>> :-)
>> No, but remember that a bootloader has to be in PE format and such a
>> format has descriptive fields in its headers. The firmware will
>> naturally only load files if it likes what it sees in the headers.
>
> you mean UEFI insists to have relocation ? what for ?

I don't know what characteristics the OS loader (or any UEFI
Application) is expected to have. I tried removing some of the library
code you now have in the disassembly I posted before. I managed to get
rid of some of it but there came a point where the firmware would no
longer load the PE file.

It's something I've to get back to. All I can say just now is that the
PE file which the firmware wouldn't load had no reloc section.


>
> I have a copy from Herbert's shortest possible PE. I'll read it again.

Sounds good. Hope you'll feed back what you come up with.


--
James Harris

wolfgang kern

unread,
Dec 1, 2023, 9:33:09 AM12/1/23
to
On 01/12/2023 14:24, James Harris wrote:

>> Isn't the first thing it loads (or tries to) a file from the FAT32
>> root directory with a certain name like "efi.bin" ?

> We were talking about /where/ UEFI loads the PE file. And you've kept
> that prior discussion in.

sorry, I forgot to skip that out

> So the change to /what/ UEFI loads is unexpected.

> But on the topic of what gets loaded ... all I can say is I don't know!
> I presume each machine can be configured with a list of things to try.
> Just like a BIOS can be configured to look for a floppy, an optical
> drive, then the first hard disk, or similar, I believe a UEFI machine
> can be configured to try a series of potentially bootable media and
> files until it gets to one which works.

so I can assume PCs with UEFI_only_ have F11 boot-options as well.

> That said, there are some standard locations, most notably

>   /efi/boot/

is this folder tree mandatory or just convenient ?

> Files in there called

>   bootARCH.efi

> are meant to be bootable for the specified architecture. ARCH could be
> such as ia32 or x64 (and yes, 3-char architecture names are OK).

OK.

> I have been testing with qemu. No idea how to configure a boot list on
> it but by default it will load either
>
>   /efi/boot/bootx64.efi
> or
>   /startup.nsh
>
> where the latter is a series of textual commands. startup.nsh is akin to
> autoexec.bat.

that's interesting, I'll check what this one can do.
...

[about relocation needs]
> Note, though, that in the previously posted disassembly the PE file
> appeared to do its own relocation.

you mean the RIP here? so it has no relocation table?

> I think the services UEFI might use to load PE files are

> EFI_BOOT_SERVICES.LoadImage
> EFI_BOOT_SERVICES.StartImage

> but from a quick scan the standards don't seem to say what either of
> them does about relocation. Probably nothing, would be my guess.

Ok, after several month I may have enough info converted to try boot on
real hardware.
...

> It's something I've to get back to. All I can say just now is that the
> PE file which the firmware wouldn't load had no reloc section.

I'm confused yet :)

>> I have a copy from Herbert's shortest possible PE. I'll read it again.
> Sounds good. Hope you'll feed back what you come up with.

Sure, but as said above it will take some time before I can run tests.

I go back now to do conversion yet, there might come more questions...

thanks for helping me old blind crossing a heavy traffic road
__
wolfgang

James Harris

unread,
Dec 2, 2023, 7:11:40 AM12/2/23
to
On 01/12/2023 14:33, wolfgang kern wrote:
> On 01/12/2023 14:24, James Harris wrote:

...

>> That said, there are some standard locations, most notably
>
>>    /efi/boot/
>
> is this folder tree mandatory or just convenient ?

According to

https://wiki.osdev.org/UEFI

Bootable UEFI applications

The boot order NVRAM variables determine where firmware will look for
UEFI applications to be launched at boot. Although this can be changed
(for example, an OS installer might customize the boot entry for the
hard drive to which it was installed) firmware typically looks for a
UEFI application named "BOOTIA32.efi" (for 32-bit applications) or
"BOOTX64.efi" (for 64-bit applications) stored in the "/EFI/BOOT" path
in the boot device's file system. This is the default path and name for
OVMF.

...

> [about relocation needs]
>> Note, though, that in the previously posted disassembly the PE file
>> appeared to do its own relocation.
>
> you mean the RIP here?  so it has no relocation table?

No, remember the very start of the disassembly (at label _start) began with

0000000000002030 <_start>:
2030: 48 83 ec 08 sub rsp,0x8
2034: 51 push rcx
2035: 52 push rdx
2036: 48 8d 3d c3 df ff ff lea
rdi,[rip+0xffffffffffffdfc3] # 0 <_text-0x2000>
203d: 48 8d 35 bc 2f 00 00 lea rsi,[rip+0x2fbc] #
5000 <_DYNAMIC>
2044: 59 pop rcx
2045: 5a pop rdx
2046: 51 push rcx
2047: 52 push rdx
2048: e8 13 00 00 00 call 2060 <_relocate>

which sure sounds like it's doing its own relocation rather than UEFI
firmware doing the relocation.

I haven't followed it through but it looks as though it is using the
dynamic relocation section (_DYNAMIC) from the PE file.


--
James Harris


James Harris

unread,
Dec 2, 2023, 7:15:47 AM12/2/23
to
On 29/11/2023 08:49, James Harris wrote:

...

> 1. x86 32-bit UEFI boot may not be widely supported. You may be better
> to be able to boot a 64-bit UEFI OS loader and switch to 32-bit mode if
> you want to start a 32-bit OS.

I knew I'd seen somewhere that 32-bit UEFI boot may not be widely
supported. I think it was at

https://forum.osdev.org/viewtopic.php?f=1&t=56668


--
James Harris

wolfgang kern

unread,
Dec 3, 2023, 4:51:38 AM12/3/23
to
On 02/12/2023 13:15, James Harris wrote:

>> 1. x86 32-bit UEFI boot may not be widely supported. You may be better
>> to be able to boot a 64-bit UEFI OS loader and switch to 32-bit mode
>> if you want to start a 32-bit OS.

Yes, that's what I have to try first even my 32-bit KESYS can switch to
LM and back, the whole thing will need a complete rewrite for the
opposite direction, I may this do later, (if I live long enough)

>
> I knew I'd seen somewhere that 32-bit UEFI boot may not be widely
> supported. I think it was at

>   https://forum.osdev.org/viewtopic.php?f=1&t=56668

I see, perhaps just contemporary on mobiles and earlier.
__
wolfgang

wolfgang kern

unread,
Dec 3, 2023, 5:06:42 AM12/3/23
to
On 02/12/2023 13:11, James Harris wrote:

>>> That said, there are some standard locations, most notably
>>
>>>    /efi/boot/
>>
>> is this folder tree mandatory or just convenient ?
>
> According to
>
>   https://wiki.osdev.org/UEFI
>
> Bootable UEFI applications
>
> The boot order NVRAM variables determine where firmware will look for
> UEFI applications to be launched at boot. Although this can be changed
> (for example, an OS installer might customize the boot entry for the
> hard drive to which it was installed) firmware typically looks for a
> UEFI application named "BOOTIA32.efi" (for 32-bit applications) or
> "BOOTX64.efi" (for 64-bit applications) stored in the "/EFI/BOOT" path
> in the boot device's file system. This is the default path and name for
> OVMF.

OK, it may be mandatory. But you know me, I'm a revolutioneer and always
try to overrule "reported" needs and get rid of all useless stuff.
I let you know how it works on real hardware when I'm there.

>> [about relocation needs]
>>> Note, though, that in the previously posted disassembly the PE file
>>> appeared to do its own relocation.
>>
>> you mean the RIP here?  so it has no relocation table?
>
> No, remember the very start of the disassembly (at label _start) began with
>
> 0000000000002030 <_start>:
>     2030:    48 83 ec 08              sub    rsp,0x8
>     2034:    51                       push   rcx
>     2035:    52                       push   rdx
>     2036:    48 8d 3d c3 df ff ff     lea
> rdi,[rip+0xffffffffffffdfc3]    # 0 <_text-0x2000>
>     203d:    48 8d 35 bc 2f 00 00     lea    rsi,[rip+0x2fbc]        #
> 5000 <_DYNAMIC>
>     2044:    59                       pop    rcx
>     2045:    5a                       pop    rdx
>     2046:    51                       push   rcx
>     2047:    52                       push   rdx
>     2048:    e8 13 00 00 00           call   2060 <_relocate>
>
> which sure sounds like it's doing its own relocation rather than UEFI
> firmware doing the relocation.
>
> I haven't followed it through but it looks as though it is using the
> dynamic relocation section (_DYNAMIC) from the PE file.

so your PE contains a relocation table, how large is it ?
how would a relocation table look like if there is not a single
reference in it ?

I checked Herbert's PE, seems it's a 32 bit format w/o any relocation.
__
wolfgang
0 new messages