Home | History | Annotate | only in /external/syslinux/gpxe/src/arch/i386
Up to higher level directory
NameDateSize
core/21-Aug-2018
drivers/21-Aug-2018
firmware/21-Aug-2018
hci/21-Aug-2018
image/21-Aug-2018
include/21-Aug-2018
interface/21-Aug-2018
kir-Makefile21-Aug-2018788
Makefile21-Aug-20183K
Makefile.efi21-Aug-2018207
Makefile.pcbios21-Aug-20181.6K
prefix/21-Aug-2018
README.i38621-Aug-20187.8K
scripts/21-Aug-2018
transitions/21-Aug-2018

README.i386

      1 Etherboot/NILO i386 initialisation path and external call interface
      2 ===================================================================
      3 
      4 1. Background
      5 
      6 GCC compiles 32-bit code.  It is capable of producing
      7 position-independent code, but the resulting binary is about 25%
      8 bigger than the corresponding fixed-position code.  Since one main use
      9 of Etherboot is as firmware to be burned into an EPROM, code size must
     10 be kept as small as possible.
     11 
     12 This means that we want to compile fixed-position code with GCC, and
     13 link it to have a predetermined start address.  The problem then is
     14 that we must know the address that the code will be loaded to when it
     15 runs.  There are several ways to solve this:
     16 
     17 1. Pick an address, link the code with this start address, then make
     18    sure that the code gets loaded at that location.  This is
     19    problematic, because we may pick an address that we later end up
     20    wanting to use to load the operating system that we're booting.
     21 
     22 2. Pick an address, link the code with this start address, then set up
     23    virtual addressing so that the virtual addresses match the
     24    link-time addresses regardless of the real physical address that
     25    the code is loaded to.  This enables us to relocate Etherboot to
     26    the top of high memory, where it will be out of the way of any
     27    loading operating system.
     28 
     29 3. Link the code with a text start address of zero and a data start
     30    address also of zero.  Use 16-bit real mode and the
     31    quasi-position-independence it gives you via segment addressing.
     32    Doing this requires that we generate 16-bit code, rather than
     33    32-bit code, and restricts us to a maximum of 64kB in each segment.
     34 
     35 There are other possible approaches (e.g. including a relocation table
     36 and code that performs standard dynamic relocation), but the three
     37 options listed above are probably the best available.
     38 
     39 Etherboot can be invoked in a variety of ways (ROM, floppy, as a PXE
     40 NBP, etc).  Several of these ways involve control being passed to
     41 Etherboot with the CPU in 16-bit real mode.  Some will involve the CPU
     42 being in 32-bit protected mode, and there's an outside chance that
     43 some may involve the CPU being in 16-bit protected mode.  We will
     44 almost certainly have to effect a CPU mode change in order to reach
     45 the mode we want to be in to execute the C code.
     46 
     47 Additionally, Etherboot may wish to call external routines, such as
     48 BIOS interrupts, which must be called in 16-bit real mode.  When
     49 providing a PXE API, Etherboot must provide a mechanism for external
     50 code to call it from 16-bit real mode.
     51 
     52 Not all i386 builds of Etherboot will want to make real-mode calls.
     53 For example, when built for LinuxBIOS rather than the standard PCBIOS,
     54 no real-mode calls are necessary.
     55 
     56 For the ultimate in PXE compatibility, we may want to build Etherboot
     57 to run permanently in real mode.
     58 
     59 There is a wide variety of potential combinations of mode switches
     60 that we may wish to implement.  There are additional complications,
     61 such as the inability to access a high-memory stack when running in
     62 real mode.
     63 
     64 2. Transition libraries
     65 
     66 To handle all these various combinations of mode switches, we have
     67 several "transition" libraries in Etherboot.  We also have the concept
     68 of an "internal" and an "external" environment.  The internal
     69 environment is the environment within which we can execute C code.
     70 The external environment is the environment of whatever external code
     71 we're trying to interface to, such as the system BIOS or a PXE NBP.
     72 
     73 As well as having a separate addressing scheme, the internal
     74 environment also has a separate stack.
     75 
     76 The transition libraries are:
     77 
     78 a) librm
     79 
     80 librm handles transitions between an external 16-bit real-mode
     81 environment and an internal 32-bit protected-mode environment with
     82 virtual addresses.
     83 
     84 b) libkir
     85 
     86 libkir handles transitions between an external 16-bit real-mode (or
     87 16:16 or 16:32 protected-mode) environment and an internal 16-bit
     88 real-mode (or 16:16 protected-mode) environment.
     89 
     90 c) libpm
     91 
     92 libpm handles transitions between an external 32-bit protected-mode
     93 environment with flat physical addresses and an internal 32-bit
     94 protected-mode environment with virtual addresses.
     95 
     96 The transition libraries handle the transitions required when
     97 Etherboot is started up for the first time, the transitions required
     98 to execute any external code, and the transitions required when
     99 Etherboot exits (if it exits).  When Etherboot provides a PXE API,
    100 they also handle the transitions required when a PXE client makes a
    101 PXE API call to Etherboot.
    102 
    103 Etherboot may use multiple transition libraries.  For example, an
    104 Etherboot ELF image does not require librm for its initial transitions
    105 from prefix to runtime, but may require librm for calling external
    106 real-mode functions.
    107 
    108 3. Setup and initialisation
    109 
    110 Etherboot is conceptually divided into the prefix, the decompressor,
    111 and the runtime image.  (For non-compressed images, the decompressor
    112 is a no-op.)  The complete image comprises all three parts and is
    113 distinct from the runtime image, which exclude the prefix and the
    114 decompressor.
    115 
    116 The prefix does several tasks:
    117 
    118   Load the complete image into memory.  (For example, the floppy
    119   prefix issues BIOS calls to load the remainder of the complete image
    120   from the floppy disk into RAM, and the ISA ROM prefix copies the ROM
    121   contents into RAM for faster access.)
    122 
    123   Call the decompressor, if the runtime image is compressed.  This
    124   decompresses the runtime image.
    125 
    126   Call the runtime image's setup() routine.  This is a routine
    127   implemented in assembly code which sets up the internal environment
    128   so that C code can execute.
    129 
    130   Call the runtime image's arch_initialise() routine.  This is a
    131   routine implemented in C which does some basic startup tasks, such
    132   as initialising the console device, obtaining a memory map and
    133   relocating the runtime image to high memory.
    134 
    135   Call the runtime image's arch_main() routine.  This records the exit
    136   mechanism requested by the prefix and calls main().  (The prefix
    137   needs to register an exit mechanism because by the time main()
    138   returns, the memory occupied by the prefix has most likely been
    139   overwritten.)
    140 
    141 When acting as a PXE ROM, the ROM prefix contains an UNDI loader
    142 routine in addition to its usual code.  The UNDI loader performs a
    143 similar sequence of steps:
    144 
    145   Load the complete image into memory.
    146 
    147   Call the decompressor.
    148 
    149   Call the runtime image's setup() routine.
    150 
    151   Call the runtime image's arch_initialise() routine.
    152 
    153   Call the runtime image's install_pxe_stack() routine.
    154 
    155   Return to caller.
    156 
    157 The runtime image's setup() routine will perform the following steps:
    158 
    159   Switch to the internal environment using an appropriate transition
    160   library.  This will record the parameters of the external
    161   environment.
    162 
    163   Set up the internal environment: load a stack, and set up a GDT for
    164   virtual addressing if virtual addressing is to be used.
    165 
    166   Switch back to the external environment using the transition
    167   library.  This will record the parameters of the internal
    168   environment.
    169 
    170 Once the setup() routine has returned, the internal environment has been
    171 set up ready for C code to run.  The prefix can call C routines using
    172 a function from the transition library.
    173 
    174 The runtime image's arch_initialise() routine will perform the
    175 following steps:
    176 
    177   Zero the bss
    178 
    179   Initialise the console device(s) and print a welcome message.
    180 
    181   Obtain a memory map via the INT 15,E820 BIOS call or suitable
    182   fallback mechanism. [not done if libkir is being used]
    183 
    184   Relocate the runtime image to the top of high memory. [not done if
    185   libkir is being used]
    186 
    187   Install librm to base memory. [done only if librm is being used]
    188 
    189   Call initialise().
    190 
    191   Return to the prefix, setting registers to indicate to the prefix
    192   the new location of the transition library, if applicable.  Which
    193   registers these are is specific to the transition library being
    194   used.
    195 
    196 Once the arch_initialise() routine has returned, the prefix will
    197 probably call arch_main().
    198