~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/arch/i386/README.i386

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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().