• [OSDev] How to switch to long mode in x86 CPUs?

    From Ar Rakin@21:1/5 to All on Thu Feb 27 21:57:01 2025
    Hello there,

    I am trying to develop my own, simple operating system to learn more
    about how kernels work and low level stuff like that. However, I am
    stuck at setting up paging while switching long mode (64-bit protected
    mode) in x86 processors.

    The assembly code I currently have:

    #define PG_START 0x000000000
    #define MSR_EFER 0xc0000080

    .section .bss, "aw", @nobits
    .align 4096
    pml4_tbl:
    .skip 4096
    pdpt_tbl:
    .skip 4096

    .text
    .globl _mboot_start
    _mboot_start:
    /* GRUB executes this code in 32-bit protected mode. */

    /* Write (pdpt_tbl | 0x3) to the first 8 bytes of pml4_tbl */
    movl $pdpt_tbl, %eax
    orl $0x3, %eax
    movl $pml4_tbl, %edi
    movl %eax, (%edi)
    xorl %eax, %eax
    movl %eax, 4(%edi)

    movl $pdpt_tbl, %edi
    movl $PG_START, %eax
    /* 0x83 = 0b10000011; flags: present, writable, upervisor-only,
    1GB huge page */
    movl $0x83, (%edi)
    movl %eax, 4(%edi)

    /* Enable Physical Address Extension (PAE) */
    movl %cr4, %eax
    btsl $5, %eax
    movl %eax, %cr4

    /* Load the address of the PML4 table into %cr3 */
    movl $pml4_tbl, %edi
    movl %edi, %cr3

    /* Enable long mode */
    movl $MSR_EFER, %ecx
    rdmsr
    btsl $8, %eax
    wrmsr

    /* Enable paging */
    movl %cr0, %eax
    btsl $31, %eax
    movl %eax, %cr0

    /* Jump to 64-bit code */
    ljmpl $0x08, $long_mode_entry
    .loop:
    hlt
    jmp .loop

    long_mode_entry:
    .code64
    xorw %ax, %ax
    movw %ax, %ds
    movw %ax, %es
    movw %ax, %fs
    movw %ax, %gs
    movw %ax, %ss

    callq kmain
    callq kabort

    I am not sure what is wrong, but when I run my kernel in
    qemu-system-x86_64, it causes a triple fault when trying to jump to the
    long mode code. After a lot of debugging, I am sure that the issue is
    with paging, because removing the ljmpl and paging instructions do not
    cause any further errors and the kernel runs fine in 32-bit mode.

    If anyone knows what is wrong with this code, please let me know. Any
    help will be appreciated!

    --
    Ar Rakin

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ar Rakin on Fri Feb 28 09:59:18 2025
    On 27/02/2025 16:57, Ar Rakin wrote:
    Hello there,

    I am trying to develop my own, simple operating system to learn more
    about how kernels work and low level stuff like that. However, I am
    stuck at setting up paging while switching long mode (64-bit protected
    mode) in x86 processors.


    Are you trying to learn about OS kernels, or about the complexities of low-level x86 stuff? Those are different things.

    If you want to learn about how operating systems work, you might
    consider starting on microcontrollers. There are lots of RTOS's
    available to study, and it is much easier to understand what is going on
    - there is none of the multi-layered disaster of x86 modes to deal with.

    Once you are happy with threads, context switches, locks, priorities,
    and all the rest of that stuff, you can start moving up and adding
    features for MMU's, SMP, and more, using bigger target processors.


    On the other hand, if you are interested in learning the intricacies of
    the x86 world, you need to look elsewhere for information - as Keith
    says, it is not really C related when you are writing assembly.
    comp.arch might be a helpful group.


    However, it is possible to use C for almost all code here. But it will
    not be standard C - it is not even standard free-standing C. You will
    make use of compiler extensions, bits of inline assembly, pre-main C
    code (so none of the library will be initialised, and program-lifetime
    data will not be set up), and other such highly non-portable code. I
    remember reading once about LinuxBIOS (now coreboot) having just four
    lines of assembly running out of reset, before everything else was in C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ar Rakin@21:1/5 to Keith Thompson on Fri Feb 28 22:18:00 2025
    On 27 Feb 2025 14:02, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Ar Rakin <rakinar2@onesoftnet.eu.org> writes:
    Hello there,

    I am trying to develop my own, simple operating system to learn more
    about how kernels work and low level stuff like that. However, I am
    stuck at setting up paging while switching long mode (64-bit protected
    mode) in x86 processors.

    The assembly code I currently have:

    [67 lines deleted]

    I am not sure what is wrong, but when I run my kernel in
    [...]

    If anyone knows what is wrong with this code, please let me know. Any
    help will be appreciated!

    You're asking about x86 assembly language, not C, so you're not likely
    to get help here. I'm not sure whether there's a newsgroup where your question would be on-topic. (comp.lang.asm.x86 appears to be dead.)

    There are no other active Usenet groups unfortunately. At least I don't
    know any.

    You might consider posting on Stack Overflow.

    That's no fun :/

    I discovered Usenet a week ago, started using it, and I'm loving it. You
    can say that I am one of those people who love retro-computing. Usenet
    is much more fun to use than web forums or things like that.

    --
    Ar Rakin

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ar Rakin@21:1/5 to David Brown on Fri Feb 28 22:30:07 2025
    On 28 Feb 2025 09:59, David Brown <david.brown@hesbynett.no> wrote:

    On 27/02/2025 16:57, Ar Rakin wrote:
    Hello there,
    I am trying to develop my own, simple operating system to learn more
    about how kernels work and low level stuff like that. However, I am
    stuck at setting up paging while switching long mode (64-bit protected
    mode) in x86 processors.


    Are you trying to learn about OS kernels, or about the complexities of low-level x86 stuff? Those are different things.

    I am just trying to learn about OS kernels, by building one.

    If you want to learn about how operating systems work, you might
    consider starting on microcontrollers. There are lots of RTOS's
    available to study, and it is much easier to understand what is going
    on - there is none of the multi-layered disaster of x86 modes to deal
    with.

    Once you are happy with threads, context switches, locks, priorities,
    and all the rest of that stuff, you can start moving up and adding
    features for MMU's, SMP, and more, using bigger target processors.

    I actually wanted to build a simple kernel that would run specifically
    on x86_64 systems. I understand why you are recommending me to learn
    about microcontrollers first, but at the moment I am almost done with
    what I wanted to achieve - I just need to fix the paging issue I
    described earlier.

    On the other hand, if you are interested in learning the intricacies
    of the x86 world, you need to look elsewhere for information - as
    Keith says, it is not really C related when you are writing
    assembly. comp.arch might be a helpful group.

    Looks like comp.arch might be the group I needed to find! Thanks.

    However, it is possible to use C for almost all code here. But it
    will not be standard C - it is not even standard free-standing C. You
    will make use of compiler extensions, bits of inline assembly,
    pre-main C code (so none of the library will be initialised, and program-lifetime data will not be set up), and other such highly
    non-portable code. I remember reading once about LinuxBIOS (now
    coreboot) having just four lines of assembly running out of reset,
    before everything else was in C.

    That is true, I could have just used C. Even articles on the osdev.org
    website heavily use C, for stuff like setting up the Global Descriptor
    Table (GDT), which I prefer to do in assembly because you would still
    need to use a special x86 assembly instruction to load the GDT (lgdt).

    I would much rather prefer having separate assembly files rather than
    inlining them in the C source files whenever possible. It's probably
    just my preference.

    Also just to clarify, from what I know, since the x86 processors start
    in 16-bit real mode for the sake of compatibility, you'd have to start
    writing 16-bit code first, then switch to 32-bit protected mode, then
    finally switch to 64-bit long mode. However if you use an existing
    bootloader such as GRUB, then you usually would not need to worry about
    16-bit code since GRUB drops you in 32-bit protected mode. But still,
    if you wish to switch to 64-bit long mode, you *will* have to mix 64-bit
    and 32-bit code together.
    Either I don't know how to, or I just don't feel comfortable mixing
    32-bit and 64-bit code together *when in C* because you will have a hard
    time linking those together. Please correct me if I am wrong.

    --
    Ar Rakin

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to rakinar2@onesoftnet.eu.org on Sat Mar 1 13:15:42 2025
    XPost: alt.os.development

    [Note: Followup-To: set to alt.os.development]

    In article <871pvje5yq.fsf@onesoftnet.eu.org>,
    Ar Rakin <rakinar2@onesoftnet.eu.org> wrote:
    Hello there,

    I am trying to develop my own, simple operating system to learn more
    about how kernels work and low level stuff like that. However, I am
    stuck at setting up paging while switching long mode (64-bit protected
    mode) in x86 processors.

    As has been mentioned, comp.lang.c is not the appropriate place
    to ask this. I have set the `Followup-To:` header to
    alt.os.development, and am cross-posting this post to that
    newsgroup.

    The assembly code I currently have:

    #define PG_START 0x000000000

    Just to be clear, this means that you have decide to make your
    _virtual_ address space starts at absolute address 0? What
    address do you link your kernel at?

    #define MSR_EFER 0xc0000080

    .section .bss, "aw", @nobits
    .align 4096
    pml4_tbl:
    .skip 4096
    pdpt_tbl:
    .skip 4096

    This is fine, but note that, instead of using code to fill in
    your page tables, you could simply define them here with the
    expected entries, as they are very simple.

    .text
    .globl _mboot_start
    _mboot_start:
    /* GRUB executes this code in 32-bit protected mode. */

    /* Write (pdpt_tbl | 0x3) to the first 8 bytes of pml4_tbl */
    movl $pdpt_tbl, %eax
    orl $0x3, %eax
    movl $pml4_tbl, %edi
    movl %eax, (%edi)

    Note that this sequence implicitly assumes that you are starting
    with an identity mapping between between the physical and
    virtual address spaces. In particular, when you
    `movl $pdpt_tbl, %eax` you are copying whatever address the
    linker assigns to `$pdpt_tbl` into %eax (the low 32-bits of it
    anyway, though the assembler would probably sqwuak at you if
    didn't fit into a 32 bit immediate). Page table entries must
    refer to physical addresses, so if you've arranged for the
    linker to use some base address other than 0 for your kernel,
    you've got to take care to account for an offset here.

    xorl %eax, %eax
    movl %eax, 4(%edi)

    Note that, as you're doing this in assembly, the upper bits in
    the table are already filled with zeros, so there's no need for
    the `xorl %eax, %eax; movl %eax 4(%edi)` sequence.

    movl $pdpt_tbl, %edi
    movl $PG_START, %eax
    /* 0x83 = 0b10000011; flags: present, writable, upervisor-only,
    1GB huge page */
    movl $0x83, (%edi)
    movl %eax, 4(%edi)

    This looks correct. Your page tables will now map a single
    gigabyte of address space starting at (virtual) address zero to
    physical address 0, and nothing else. To be clear, is that what
    you want? When coming out of protected mode, I generally try to
    map the whole 32-bit address space; that is, all 4 GiB.

    /* Enable Physical Address Extension (PAE) */
    movl %cr4, %eax
    btsl $5, %eax
    movl %eax, %cr4

    /* Load the address of the PML4 table into %cr3 */
    movl $pml4_tbl, %edi
    movl %edi, %cr3

    Note that the same caveat about physical addresses of the PML4
    apply here as applied to the PDPT above.

    /* Enable long mode */
    movl $MSR_EFER, %ecx
    rdmsr
    btsl $8, %eax
    wrmsr

    /* Enable paging */
    movl %cr0, %eax
    btsl $31, %eax
    movl %eax, %cr0

    So immediately after executing this instruction, the processor
    will be executing with paging enabled. This means that the very
    next instruction (the ljmp below here) _must_ be mapped at the
    address in %rip. If not, you will fault.

    Your post suggests that you fault on the ljmp, but this may not
    be why. Any easy test would be to add a `jmp .` here and see if
    that faults in the QEMU monitor.

    If you do not fault here, then your page tables are ok (at least
    so far), and your problem lies elsewhere. See below.

    /* Jump to 64-bit code */
    ljmpl $0x08, $long_mode_entry

    Have you set up a GDT with an entry for a 64-bit code segment
    by this point? It doesn't look like it. My guess is that that
    is the source of your fault; note that the multiboot1 spec says
    that you must set up a GDT and should not rely on the one that
    it set up to get you into 32-bit protected mode. Certainly
    there is no guarantee that there's a 64-bit code segment at
    offset 0x8 in whatever table it set up.

    My guess is that this is the source of your problem.

    .loop:
    hlt
    jmp .loop

    I would delete this loop; you can't ever really hit it: either
    the long jump will succeed and skip over it, or it will fault.

    long_mode_entry:
    .code64
    xorw %ax, %ax
    movw %ax, %ds
    movw %ax, %es
    movw %ax, %fs
    movw %ax, %gs
    movw %ax, %ss

    callq kmain

    You should probably give yourself a stack before calling C.
    What's in `%rsp` here? My guess is that this would fault if you
    got here: the `callq` will push the address of the next
    instruction onto the stack, but since you haven't set one up,
    %rsp is whatever it is (either it's reset value, 0, or something
    random set up by multiboot). Suppose it's 0; then the call will
    attempt to push %rip to -8; that's fine (the processor will
    happily wrap around to 0xfffffffffffffff8) but you definitely
    don't have anything mapped there, so you'll get a fault.

    In 32-bit mode, this will wrap around to 0xfffffff8, which is
    in the active stack segment; there may be RAM there, which is
    why it doesn't fault in protected mode.

    Since you haven't set up an IDT yet, any fault this early will
    be a triple fault.

    Or perhaps multiboot left you a stack by chance. The multiboot1
    specification explicitly says that the OS should set up it's own
    stack, though, so I wouldn't rely on that.

    Try adding a page for more for stack space in your BSS, and set
    %rsp to point to the top of that region, e.g., back in bss:

    stack:
    .skip 4096

    ...

    movabsq $(stack + 4096), %rsp
    callq kmain

    callq kabort

    I take it you never get here. :-)

    I am not sure what is wrong, but when I run my kernel in
    qemu-system-x86_64, it causes a triple fault when trying to jump to the
    long mode code. After a lot of debugging, I am sure that the issue is
    with paging, because removing the ljmpl and paging instructions do not
    cause any further errors and the kernel runs fine in 32-bit mode.

    My guess is that, assuming you're correctly referring to the
    physical address of your page table structures as I mentioned
    above, paging is fine, but rather, it's segmentation that's
    causing the problem.

    If anyone knows what is wrong with this code, please let me know. Any
    help will be appreciated!

    At a minimum, set up a GDT for yourself and give yourself a
    proper stack before calling into C code; a lot of context, in
    particular your linker configuration, is missing so it's hard to
    say whether those are the only problems.

    You may want to consider using named constants in place of the
    manifest values you've got now when setting bits and so forth.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to rakinar2@onesoftnet.eu.org on Sat Mar 1 13:34:42 2025
    XPost: alt.os.development

    [Note: Followup-To: alt.os.development]

    In article <875xkughgw.fsf@onesoftnet.eu.org>,
    Ar Rakin <rakinar2@onesoftnet.eu.org> wrote:
    On 28 Feb 2025 09:59, David Brown <david.brown@hesbynett.no> wrote:
    [snip]
    On the other hand, if you are interested in learning the intricacies
    of the x86 world, you need to look elsewhere for information - as
    Keith says, it is not really C related when you are writing
    assembly. comp.arch might be a helpful group.

    Looks like comp.arch might be the group I needed to find! Thanks.

    Comp.arch is not a good choice here. It's for discussion of
    computer architecutre generally, specifics of how to boot an x86
    core would be mostly tangential.

    alt.os.development is probably your best bet, but please try not
    to feed the troll there.

    [snip]
    Also just to clarify, from what I know, since the x86 processors start
    in 16-bit real mode for the sake of compatibility, you'd have to start >writing 16-bit code first, then switch to 32-bit protected mode, then
    finally switch to 64-bit long mode. However if you use an existing >bootloader such as GRUB, then you usually would not need to worry about >16-bit code since GRUB drops you in 32-bit protected mode. But still,
    if you wish to switch to 64-bit long mode, you *will* have to mix 64-bit
    and 32-bit code together.

    Either I don't know how to, or I just don't feel comfortable mixing
    32-bit and 64-bit code together *when in C* because you will have a hard
    time linking those together. Please correct me if I am wrong.

    Eh...It can be done, but I don't see the point. Even starting
    from the reset vector (e.g., in 16-bit 8086 mode) it's not that
    many instructions to get yourself into long mode with paging
    enabled. To see an example of how this is done, have a look at: https://github.com/oxidecomputer/phbl/blob/main/src/start.S

    It's sufficient straight-forward, and so low-level, that doing
    this in a high-level language doesn't seem worth it from a
    cost/benefit perspective.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Paul Edwards on Sat Mar 1 14:55:37 2025
    "Paul Edwards" <mutazilah@gmail.com> writes:
    "David Brown" <david.brown@hesbynett.no> wrote in message >news:vprtt6$3jah9$1@dont-email.me...
    On 27/02/2025 16:57, Ar Rakin wrote:


    Do you consider the concept of a BIOS (as seen as the IBM PC),
    "legitimate to use"

    In the abstract, possibly. But the last half century has
    shown that BIOS as an I/O abstraction layer was a bad idea
    from the start.

    and do you consider MSDOS (which uses that
    BIOS) to be an operating system?

    No, MSDOS was, is, will always be a simple program loader.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Ar Rakin on Fri Feb 28 18:25:31 2025
    Ar Rakin <rakinar2@onesoftnet.eu.org> wrote:

    There are no other active Usenet groups unfortunately. At least I don't
    know any.

    There alt.os.development and (IIRC) alt.os.assembly which are quite
    good fit for your question. They have little trafic now, but there
    are people reading them and answering.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Salvador Mirzo@21:1/5 to Scott Lurndal on Sat Mar 1 23:37:15 2025
    scott@slp53.sl.home (Scott Lurndal) writes:

    "Paul Edwards" <mutazilah@gmail.com> writes:
    "David Brown" <david.brown@hesbynett.no> wrote in message >>news:vprtt6$3jah9$1@dont-email.me...
    On 27/02/2025 16:57, Ar Rakin wrote:


    Do you consider the concept of a BIOS (as seen as the IBM PC),
    "legitimate to use"

    In the abstract, possibly. But the last half century has
    shown that BIOS as an I/O abstraction layer was a bad idea
    from the start.

    Would you elaborate or point out an article or book that could clarify
    the ideas that have made you to make such remark? Sounds interesting.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy Valencia@21:1/5 to Dan Cross on Sat Mar 1 20:02:57 2025
    XPost: alt.os.development

    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    I am trying to develop my own, simple operating system to learn more
    about how kernels work and low level stuff like that. However, I am
    stuck at setting up paging while switching long mode (64-bit protected >mode) in x86 processors.

    Two things in addition to the fellow who cross-posted this and gave
    you some great analysis.

    1. If you use bochs, you can single step the emulator itself, and
    basically have a microcode view of what the processor's trying to do
    with your code. This can save you _tons_ of time.

    2. You should crib from working code. For 32-bit x86, may I humbly
    point at my protected mode microkernel, VSTa:

    https://sources.vsta.org:7100/vsta/index

    Andy Valencia
    Home page: https://www.vsta.org/andy/
    To contact me: https://www.vsta.org/contact/andy.html
    Fediverse: @vandys@goto.vsta.org

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Paul Edwards on Sun Mar 2 16:16:27 2025
    On 02/03/2025 08:22, Paul Edwards wrote:
    "Scott Lurndal" <scott@slp53.sl.home> wrote in message news:JdFwP.46247$SZca.36276@fx13.iad...
    "Paul Edwards" <mutazilah@gmail.com> writes:
    "David Brown" <david.brown@hesbynett.no> wrote in message
    news:vprtt6$3jah9$1@dont-email.me...
    On 27/02/2025 16:57, Ar Rakin wrote:


    Do you consider the concept of a BIOS (as seen as the IBM PC),
    "legitimate to use"

    In the abstract, possibly. But the last half century has
    shown that BIOS as an I/O abstraction layer was a bad idea
    from the start.

    and do you consider MSDOS (which uses that
    BIOS) to be an operating system?

    No, MSDOS was, is, will always be a simple program loader.

    Plus manages memory.

    How does it do that? I seem to recall that you got 640KB minus whatever
    the resident parts of the OS needed.

    Plus manages file systems
    Plus provides an API
    Plus provides a device driver interface
    Plus provides a command shell
    Plus provides other utilities

    My memories of it was that it provided a file system used via some API,
    and some keyboard and text screen i/o (I can't remember if it handled a
    mouse).

    It didn't provide drivers for graphics hardware, or low level libraries
    for it, or GUI libraries, or printer or plotter drivers (whatever was
    necessary for vector and raster outputs), or floating point libraries ...

    Which was fine by me. I just needed it to load and run my program, which usually switched the machine to some graphics mode, and when it
    terminated it went back to the DOS command prompt in text mode, and the
    user could then run some other program.

    I wish Windows was still that simple.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Salvador Mirzo on Sun Mar 2 16:42:48 2025
    Salvador Mirzo <smirzo@example.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    "Paul Edwards" <mutazilah@gmail.com> writes:
    "David Brown" <david.brown@hesbynett.no> wrote in message >>>news:vprtt6$3jah9$1@dont-email.me...
    On 27/02/2025 16:57, Ar Rakin wrote:


    Do you consider the concept of a BIOS (as seen as the IBM PC), >>>"legitimate to use"

    In the abstract, possibly. But the last half century has
    shown that BIOS as an I/O abstraction layer was a bad idea
    from the start.

    Would you elaborate or point out an article or book that could clarify
    the ideas that have made you to make such remark? Sounds interesting.

    When the BIOS (as was originally intended) controls all the I/O interfaces,
    it fundamentally limits access to new and experimental devices, and limits
    the ability to generationally improve the hardware (e.g. Compare NVMe driver interface with a legacy ISA device vis-a-vis the OS interface to the device).

    It requires the mainboard manufacturer that provides the BIOS include
    support for all new third-party hardware innovations. Given the BIOS
    was orignally a ROM, such systems were extremely difficult to update
    and there was no way to accomodate new third-party hardware without
    bypassing the BIOS entirely.

    The expansion ROM on PCI was an attempt to remedy this, but clearly
    falls short when supporting multiple hardware families (e.g. various
    RISC and CISC architectures) pushing the burden to support new
    or different operating systems upon the device hardware manufacturer;
    which either requires differnent SKUs for each generation of each
    supported processor family, a significant burden on the device hardware manufacturer.

    BIOS is a least-common-denominator hardware abstraction interface.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to Scott Lurndal on Sun Mar 2 20:26:31 2025
    XPost: alt.os.development

    [Note: Following up to alt.os.development]

    I think there's an interesting discussion to be had here, but I
    think it would be best outside of comp.lang.c. I wish there was
    a comp.* group for this (bring back comp.os.research!) but
    alt.os.development is probably closest.

    In article <cU%wP.111376$_N6e.73667@fx17.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:
    Salvador Mirzo <smirzo@example.com> writes:
    [snip]
    Would you elaborate or point out an article or book that could clarify
    the ideas that have made you to make such remark? Sounds interesting.

    When the BIOS (as was originally intended) controls all the I/O interfaces, >it fundamentally limits access to new and experimental devices, and limits >the ability to generationally improve the hardware (e.g. Compare NVMe driver >interface with a legacy ISA device vis-a-vis the OS interface to the device).

    It certainly means that, for example, an OS-provided filesystem
    that can only access a storage device via the BIOS can't use
    those devices. These primitive early PC "operating systems"
    didn't provide any real memory safety, or try to prevent
    programs from accessing the hardware directly, bypassing the OS.
    So in theory a user program could talk directly to the device,
    but then it has to go implement a filesystem (or something
    equivalent) itself, and every program that wants to use that
    data has to know how to talk to that device. That obviously
    defeats the purpose of having the OS provide the abstraction.

    It requires the mainboard manufacturer that provides the BIOS include
    support for all new third-party hardware innovations. Given the BIOS
    was orignally a ROM, such systems were extremely difficult to update
    and there was no way to accomodate new third-party hardware without
    bypassing the BIOS entirely.

    +1e6

    The expansion ROM on PCI was an attempt to remedy this, but clearly
    falls short when supporting multiple hardware families (e.g. various
    RISC and CISC architectures) pushing the burden to support new
    or different operating systems upon the device hardware manufacturer;
    which either requires differnent SKUs for each generation of each
    supported processor family, a significant burden on the device hardware >manufacturer.

    I'm going to quibble with this one a little bit.

    To my mind, modern firmware, including BIOS-like systems,
    provides three fundamental facilities:

    1. It provides an abstraction interface for systems software,
    both the traditional BIOS role, but also a way to decouple
    emulate legacy hardware interfaces so that hardware
    advances are decoupled from systems software. Consider
    running DOS on a machine with a USB keyboard and mouse;
    "BIOS" gives me a way to emulate an AT or PS/2 keyboard.
    (Don't get me started on the dumpster fire that is SMM.)
    2. It's a place to do all sorts of platform enablement. For
    example, on modern x86 systems, firmware does DRAM timing
    training, IO bus enumeration and initial allocation and
    assignment of physical address space for MMIO, bridge
    assignment and configuration, etc.
    3. It solves a necessary bootstrapping problem. Often, an
    operating system is installed on some storage device that
    sits on some controller somewhere. But in order to load the
    OS, I have to be able to initialize and drive the controller
    "enough" to be able to load the OS (or at least some kind of
    boot loader that knows to to load the OS). Firmware that
    understands enough of the platform to do the bare minimum to
    drive hardware and load a more elaborate bootstrap let's me
    boot a real system.

    Options ROMs were meant as part of the solution to last problem:
    give the hardware enough smarts so that very simple code running
    in a very constrained early boot environment could get something
    from the device itself that lets the firmware drive the device
    well enough to load more capable software from it. With a
    well-defined and sufficiently capable interface between the
    option ROM and firmware, third-party hardware designed well
    after a system was put in place can be used on that system,
    provided the OS it uses has been updated so that it can drive
    the new hardware.

    I don't think this is a bad way to do things, to be honest;
    interfaces are fundamental for isolation in software. And the
    way that OpenFirmware did it was actually pretty nice: provide
    an interpreter for a sufficiently general language (FORTH) in
    firmware, and store little programs in that language in ROM on
    the device that let firmware drive the device enough to load a
    real OS. Pair firmware with a little bit of non-volatile
    storage like battery-backed CMOS so that you can store a few
    variables, and you're good to go.

    But of course, the expression of the idea in UEFI has become a
    bloated and insecure mess that creeped into everything, and you
    can't really get rid of it, even once the OS is running.

    BIOS is a least-common-denominator hardware abstraction interface.

    This times 100. BIOS wasn't just there to bootstrap, it was
    meant to be _the_ interface to the hardware, as you point out.
    That was fine on the anemic Z80-based machines that CP/M ran on,
    but it's awful once you want to do something more complex.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Paul Edwards on Tue Mar 4 20:27:43 2025
    On 04/03/2025 18:31, Paul Edwards wrote:
    "bart" <bc@freeuk.com> wrote in message news:vq208q$re74$1@dont-email.me...
    On 02/03/2025 08:22, Paul Edwards wrote:
    "Scott Lurndal" <scott@slp53.sl.home> wrote in message
    news:JdFwP.46247$SZca.36276@fx13.iad...
    "Paul Edwards" <mutazilah@gmail.com> writes:
    "David Brown" <david.brown@hesbynett.no> wrote in message
    news:vprtt6$3jah9$1@dont-email.me...
    On 27/02/2025 16:57, Ar Rakin wrote:


    Do you consider the concept of a BIOS (as seen as the IBM PC),
    "legitimate to use"

    In the abstract, possibly. But the last half century has
    shown that BIOS as an I/O abstraction layer was a bad idea
    from the start.

    and do you consider MSDOS (which uses that
    BIOS) to be an operating system?

    No, MSDOS was, is, will always be a simple program loader.

    Plus manages memory.

    How does it do that? I seem to recall that you got 640KB minus whatever
    the resident parts of the OS needed.

    Yes - and? Then you need to manage that memory, so you
    need a memory manager, which MSDOS provides. It's not
    trivial to write/debug one of those either.

    I'm not sure what your question is exactly, so I'll include code
    to call the interrupt (21H AH=48H) you need to obtain memory.

    I was questioning whether MSDOS provided means to manage memory, since I
    don't recall anything like that. My programs handled their own memory as
    they did most other things.

    This 0x48/48H syscall is new to me.

    (But it also looks like something it wouldn't use anyway, since it
    appears to work like malloc in storing the allocated size. That's
    something I would never need, and would be wasteful with the limited
    memory available.

    Because I will either know the fixed size of the object I want to freed,
    or would need to keep a record of it anyway if it's more dynamic.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)