Introduction:
I am just bringing the BLDR size issues we faced when we tried to add more functionalities to the X86 bootloader (BLDR).
As per the current X86 bootloader designs in Windows CE, we can only build the BIOS boot loader of size 20 KB, which was overlapped when we add some additional functionality to the bootloader.
Size Limitation:
The X86 architecture has 2 modes of operation. The REAL mode and PROTECTED mode. All the X86 processors boot up in real mode and BIOS works only in real mode. All the modern Operating Systems after being loaded in to the memory by the boot loader configures the CPU in protected mode and runs on the same. There is no need for these operating systems to switch back to real mode, as they have custom drivers built to operate in protected mode for all accesses to I/O devices, leaving BIOS untouched after the OS takes control.
In the real mode the operation is 16 Bit and hence the address space seen by the processor is only 64KB. With the help of segment registers this can go up to a maximum of 1MB but not more than that.
In protected mode, the entire 32 bit can be used and as a result all the 4GB can be addressed.
The BIOS actually starts in real mode and calls the extended BIOS as well in the real mode. BIOS is capable of accessing only the 64KB address space.
Options tried to increase the size:
1. Flat Real Mode:
Flat real mode is a popular name for a technique used to access up to 4GB of memory, while the processor is remaining in real mode. This technique requires a 80386 or higher processor. The address space really is not flat. Actually, this technique allows you treat one or more segments as large (32-bit) segments, thereby accessing memory above 1 MB, up to 4GB of memory
But this mode didn’t help us, this also requires the data segment, stack segment and code segment to be in first 64 KB of memory to make the bios calls. Though we can access 4GB of memory, we would not be able to increase the code size beyond 64kb segment.
2. Then we tried to build the BLDR with the architecture as follows. The BLDR size will be more than 64 KB. In that the real mode routine which makes BIOS calls will be placed in the first 24 KB memory. And the other routines which are called in protected mode will be resided in the memory greater than 64KB. The in between memory area (from 24KB to 64KB) will be filled with 0s. So, this area will be used for Stack and other purposes in real mode.
The idea is to divide the BIOS in to two parts one that executes in protected mode and another section executing in real mode (which makes the BIOS calls). If the protected mode code is required to access BIOS routines, then the code in the protected will call a wrapper in the real mode BIOS, which will switch the CPU to real mode and make the corresponding BIOS call and return the result to the original called after switching back to protected mode and keeping the return values from BIOS intact.
This requires grouping of text section of code in to two parts and assigning the start address for each of these sections. But the Microsoft compiler and linker does not support to build the BLDR like this. The MS compiler supports providing only one start address that will be the start of execution of code. We can not fix the load address of some functions in a single executable code arbitrarily using the options provided by MS build tools
Maximum BLDR Size:
The 64KB address space split up can be seen in the boot.bib
BLDR 00001000 00005000 RAMIMAGE ;
Size should be evenly divisible by 512b.
BPB 00007C00 00000050 RESERVED ;
BIOS parameter block data and DPT.
VESA 00008000 00001000 RESERVED ;
VESA work RAM.
RAM 00009000 00001900 RAM
SCACHE 0000A900 00000200 RESERVED ;
Sector cache.
STACK 0000AB00 00001500 RESERVED ;
Stack base will be set to 0x7FFC to leave 0x8000 free.
READBUF 0000C000 00004000 RESERVED ;
Sector read buffer.
By adjusting the split up size we can achieve maximum of 34KB BLDR size. Do the following to achieve
1. Change the boot.bib as follows
BLDR 00001000 00009600 RAMIMAGE ;
Size should be evenly divisible by 512b.
BPB 0000A600 00000050 RESERVED ;
BIOS parameter block data and DPT
VESA 0000A800 00001000 RESERVED ;
VESA work RAM.
RAM 0000B800 00001100 RAM
SCACHE 0000C900 00000200 RESERVED ;
Sector cache.
STACK 0000CB00 00001500 RESERVED ;
Stack base will be set to 0x7FFC to leave 0x8000 free.
READBUF 0000E000 00002000 RESERVED ;
Sector read buffer.
CONFIG
; ROM info
ROMSTART=00001000
ROMSIZE=09600
2. Change the following definition:
File Name | Definition | Default Value | Change Value |
Bldr.h | VESA_GENINFO_START | ((VESA_GENERAL_INFO *)0x8000 | ((VESA_GENERAL_INFO *)0xA800 |
Bldr.inc | STACK_BASE | 0BFFCh | 0DFFCh |
Bldr.inc | VESA_GENINFO_START | 0x8000 | 0xA800 |
Bldr.inc | READ_BUFFER_START | 0xC000 | 0xE000 |
Fat.h | READ_BUFFER_START | 0xC000 | 0xE000 |
Fat.h | READ_BUFFER_LENGTH_MAX | 0x3000 | 0x1000 |
Fat.h | SECTOR_CACHE_START | 0xA900 | 0xC900 |