Octocontrabass wrote:rdos wrote:Actually, it's just as easy to load a code selector with a zero base as a non-zero base. If you load your second stage boot loader at a fixed segment, you can safely use a fixed base for the code segment in protected mode.
But then you either need to write your code directly in assembly or use a toolchain that supports nonzero segment bases, and then your code won't be portable to 64-bit mode or any non-x86 CPU. (This isn't really a concern for a bootloader, but it is for the rest of the OS.)
I don't see any valid reason why bootloaders or second stage loaders would not be coded completely in assembly. Portability of boot-loaders is a non-issue. Besides, if you want portability, use EFI as EFI code is portable.
Besides, the x86 boot loader ALWAYS run in real mode, and so portability to long mode is a non-issue. The boot loader should just load the operating system image, and then at the very end setup the correct mode, either a 32-bit environment or a 64-bit and pass control to the kernel. It's also possible, and probably even the best, to start the operating system in protected mode without paging, and then let the operating system setup paging and possibly switch mode to long mode. That's the way my BIOS based boot loader works. The 32-bit EFI based loader will switch from protected mode with unity paging to a non-paged mode and then start the kernel without paging. The 64-bit EFI based loader will turn off long mode and enable protected mode without paging and then start the kernel.
Octocontrabass wrote:
rdos wrote:There certainly is a need to create a 4G flat selector too, but code should not be using orgs or similar.
Why shouldn't it? Most C compilers use 0 as their internal representation for null pointers, so you don't want any valid code or data at address 0 to catch null pointer references.
With segmentation, you cannot even access it without loading a flat selector.
Octocontrabass wrote:
rdos wrote:My original tool chain in 1988 was a DOS-based assembler & linker.
Toolchain documentation is easier to find nowadays than it was in 1988.
I use OpenWatcom for most things today. The boot sector uses a special linker mode that creates a binary image. The same is used for the second stage loader. Device drivers can be 16-bit or 32-bit, and the 32-bit version can use C, although most are still in pure assembly. The model the C compiler sets up is a 32-bit segmented mode with a predefined code and data selector with exact limits per device driver. This way, code cannot be executed outside of the driver, and static data cannot be accessed outside of the default data segment. External pointers are 48-bit, but references to code and default data use 32-bit offsets. Applications are currently only 32-bit flat, but other models are possible.
The only thing that OpenWatcom cannot handle is the EFI loaders. These are compiled with 32-bit and 64-bit cygwin.
Of course, GCC would be unable to build the BIOS boot loaders, as well as the kernel device drivers. GCC could be used for applications, but the problem there is that the inline assembly syntax differs (Intel vs AT&T) and would require two versions of every syscall macro.