From 53a5de3641ccd0836aac7378cdd37c9757e2db3a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 13 Jan 2022 12:48:38 +0000 Subject: [doc] Update user-visible ipxe.org URIs to use HTTPS Signed-off-by: Michael Brown --- src/arch/x86/prefix/romprefix.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/arch/x86/prefix') diff --git a/src/arch/x86/prefix/romprefix.S b/src/arch/x86/prefix/romprefix.S index a9934a725..4e8793c21 100644 --- a/src/arch/x86/prefix/romprefix.S +++ b/src/arch/x86/prefix/romprefix.S @@ -161,7 +161,7 @@ pnpheader: /* Manufacturer string */ mfgstr: - .asciz "http://ipxe.org" + .asciz "https://ipxe.org" .size mfgstr, . - mfgstr /* Product string @@ -607,7 +607,7 @@ get_pmm_decompress_to: * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/branding.h. * * While nothing in the GPL prevents you from removing all references - * to iPXE or http://ipxe.org, we prefer you not to do so. + * to iPXE or https://ipxe.org, we prefer you not to do so. * * If you have an OEM-mandated branding requirement that cannot be * satisfied simply by defining PRODUCT_NAME and PRODUCT_SHORT_NAME, -- cgit v1.2.3-55-g7522 From bc35b24e3ebd2996b2484b7f9ceb96a3cf25823a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 2 Feb 2022 03:26:20 +0000 Subject: [prefix] Fix use of writable code segment on 486 and earlier CPUs In real mode, code segments are always writable. In protected mode, code segments can never be writable. The precise implementation of this attribute differs between CPU generations, with subtly different behaviour arising on the transitions from protected mode to real mode. At the point of transition (when the PE bit is cleared in CR0) the hidden portion of the %cs descriptor will retain whatever attributes were in place for the protected-mode code segment, including the fact that the segment is not writable. The immediately following code will perform a far control flow transfer (such as ljmp or lret) in order to load a real-mode value into %cs. On the Pentium and later CPUs, the retained protected-mode attributes will be ignored for any accesses via %cs while the CPU is in real mode. A write via %cs will therefore be allowed even though the hidden portion of the %cs descriptor still describes a non-writable segment. On the 486 and earlier CPUs, the retained protected-mode attributes will not be ignored for accesses via %cs. A write via %cs will therefore cause a CPU fault. To obtain normal real-mode behaviour (i.e. a writable %cs descriptor), special logic is added to the ljmp instruction that populates the hidden portion of the %cs descriptor with real-mode attributes when a far jump is executed in real mode. The result is that writes via %cs will cause a CPU fault until the first ljmp instruction is executed, after which writes via %cs will be allowed as expected in real mode. The transition code in libprefix.S currently uses lret to load a real-mode value into %cs after clearing the PE bit. Experimentation shows that only the ljmp instruction will work to load real-mode attributes into the hidden portion of the %cs descriptor: other far control flow transfers (such as lret, lcall, or int) do not do so. When running on a 486 or earlier CPU, this results in code within libprefix.S running with a non-writable code segment after a mode transition, which in turn results in a CPU fault when real-mode code in liba20.S attempts to write to %cs:enable_a20_method. Fix by constructing and executing an ljmp instruction, to trigger the relevant descriptor population logic on 486 and earlier CPUs. This ljmp instruction is constructed on the stack, since the .prefix section may be executing directly from ROM (or from memory that the BIOS has write-protected in order to emulate an ISA ROM region) and so cannot be modified. Reported-by: Nikolai Zhubr Signed-off-by: Michael Brown --- src/arch/x86/prefix/libprefix.S | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/arch/x86/prefix') diff --git a/src/arch/x86/prefix/libprefix.S b/src/arch/x86/prefix/libprefix.S index ffb211058..d7f261957 100644 --- a/src/arch/x86/prefix/libprefix.S +++ b/src/arch/x86/prefix/libprefix.S @@ -380,6 +380,11 @@ process_bytes: pushl %eax pushl %ebp + /* Construct ljmp code on stack (since .prefix may not be writable) */ + .equ LJMP_LEN, 0x06 + pushw %cs /* "nop ; ljmp %cs, $2f" */ + pushw $2f + pushw $0xea90 /* Construct GDT on stack (since .prefix may not be writable) */ .equ GDT_LEN, 0x20 .equ PM_DS, 0x18 /* Flat data segment */ @@ -410,8 +415,9 @@ process_bytes: pushw %es pushw %ds pushw %ss - pushw %cs - pushw $2f + pushw %ss /* Far pointer to ljmp code on stack */ + leaw (GDT_LEN + 1)(%bp), %ax + pushw %ax cli data32 lgdt (%bp) movl %cr0, %eax @@ -438,7 +444,7 @@ process_bytes: popfw movl %eax, %cr0 lret -2: /* lret will ljmp to here */ +2: /* lret will ljmp to here (via constructed ljmp on stack) */ popw %ss popw %ds popw %es @@ -461,7 +467,7 @@ process_bytes: /* Restore GDT */ data32 lgdt -8(%bp) - leaw GDT_LEN(%bp), %sp + leaw (GDT_LEN + LJMP_LEN)(%bp), %sp /* Restore registers and return */ popl %ebp -- cgit v1.2.3-55-g7522