Browse Source

Initial revision

tags/v0.9.3
Michael Brown 19 years ago
commit
3d6123e69a
100 changed files with 13160 additions and 0 deletions
  1. 2
    0
      src/.cvsignore
  2. 450
    0
      src/Config
  3. 133
    0
      src/Families
  4. 15
    0
      src/Makefile
  5. 18
    0
      src/Makefile-armnommu
  6. 18
    0
      src/Makefile-e1
  7. 18
    0
      src/Makefile-i386
  8. 18
    0
      src/Makefile-ia64
  9. 450
    0
      src/Makefile.main
  10. 90
    0
      src/README.pixify
  11. 23
    0
      src/arch/armnommu/Config
  12. 58
    0
      src/arch/armnommu/Makefile
  13. 77
    0
      src/arch/armnommu/core/arm_timer.c
  14. 55
    0
      src/arch/armnommu/core/etherboot.lds
  15. 105
    0
      src/arch/armnommu/core/lib1funcs.c
  16. 27
    0
      src/arch/armnommu/core/mem.c
  17. 48
    0
      src/arch/armnommu/core/raw_loader.c
  18. 66
    0
      src/arch/armnommu/core/serial.c
  19. 33
    0
      src/arch/armnommu/core/setjmp.S
  20. 184
    0
      src/arch/armnommu/core/start.S
  21. 525
    0
      src/arch/armnommu/drivers/net/p2001_eth.c
  22. 47
    0
      src/arch/armnommu/include/bits/byteswap.h
  23. 13
    0
      src/arch/armnommu/include/bits/cpu.h
  24. 18
    0
      src/arch/armnommu/include/bits/elf.h
  25. 17
    0
      src/arch/armnommu/include/bits/endian.h
  26. 11
    0
      src/arch/armnommu/include/bits/string.h
  27. 1
    0
      src/arch/armnommu/include/callbacks_arch.h
  28. 179
    0
      src/arch/armnommu/include/hardware.h
  29. 25
    0
      src/arch/armnommu/include/hooks.h
  30. 27
    0
      src/arch/armnommu/include/io.h
  31. 15
    0
      src/arch/armnommu/include/latch.h
  32. 43
    0
      src/arch/armnommu/include/limits.h
  33. 30
    0
      src/arch/armnommu/include/lxt971a.h
  34. 23
    0
      src/arch/armnommu/include/setjmp.h
  35. 23
    0
      src/arch/armnommu/include/stdint.h
  36. 7
    0
      src/arch/e1/Config
  37. 70
    0
      src/arch/e1/Makefile
  38. 67
    0
      src/arch/e1/Makefile.working
  39. 80
    0
      src/arch/e1/README
  40. 176
    0
      src/arch/e1/core/coff_loader.c
  41. 70
    0
      src/arch/e1/core/e132_xs.c
  42. 94
    0
      src/arch/e1/core/e1_timer.c
  43. 126
    0
      src/arch/e1/core/etherboot.lds
  44. 35
    0
      src/arch/e1/core/longjmp.c
  45. 54
    0
      src/arch/e1/core/memcmp.S
  46. 79
    0
      src/arch/e1/core/memcpy.S
  47. 47
    0
      src/arch/e1/core/memset.S
  48. 26
    0
      src/arch/e1/core/setjmp.c
  49. 111
    0
      src/arch/e1/core/start.S
  50. 76
    0
      src/arch/e1/core/strcmp.S
  51. 39
    0
      src/arch/e1/include/bits/byteswap.h
  52. 6
    0
      src/arch/e1/include/bits/cpu.h
  53. 6
    0
      src/arch/e1/include/bits/elf.h
  54. 6
    0
      src/arch/e1/include/bits/endian.h
  55. 35
    0
      src/arch/e1/include/bits/string.h
  56. 22
    0
      src/arch/e1/include/e132_xs_board.h
  57. 9
    0
      src/arch/e1/include/hooks.h
  58. 210
    0
      src/arch/e1/include/io.h
  59. 12
    0
      src/arch/e1/include/latch.h
  60. 34
    0
      src/arch/e1/include/limits.h
  61. 23
    0
      src/arch/e1/include/setjmp.h
  62. 16
    0
      src/arch/e1/include/stdint.h
  63. 131
    0
      src/arch/i386/Config
  64. 373
    0
      src/arch/i386/Makefile
  65. 144
    0
      src/arch/i386/core/aout_loader.c
  66. 107
    0
      src/arch/i386/core/callbacks.c
  67. 86
    0
      src/arch/i386/core/cpu.c
  68. 135
    0
      src/arch/i386/core/elf.c
  69. 90
    0
      src/arch/i386/core/etherboot.lds
  70. 100
    0
      src/arch/i386/core/etherboot.prefix.lds
  71. 377
    0
      src/arch/i386/core/freebsd_loader.c
  72. 35
    0
      src/arch/i386/core/hooks.c
  73. 191
    0
      src/arch/i386/core/i386_timer.c
  74. 305
    0
      src/arch/i386/core/init.S
  75. 143
    0
      src/arch/i386/core/multiboot_loader.c
  76. 352
    0
      src/arch/i386/core/pci_io.c
  77. 331
    0
      src/arch/i386/core/pic8259.c
  78. 8
    0
      src/arch/i386/core/prefixudata.lds
  79. 8
    0
      src/arch/i386/core/prefixzdata.lds
  80. 364
    0
      src/arch/i386/core/pxe_callbacks.c
  81. 94
    0
      src/arch/i386/core/pxe_loader.c
  82. 148
    0
      src/arch/i386/core/realmode.c
  83. 695
    0
      src/arch/i386/core/realmode_asm.S
  84. 285
    0
      src/arch/i386/core/start16.S
  85. 8
    0
      src/arch/i386/core/start16.lds
  86. 65
    0
      src/arch/i386/core/start16z.lds
  87. 767
    0
      src/arch/i386/core/start32.S
  88. 201
    0
      src/arch/i386/core/tagged_loader.c
  89. 94
    0
      src/arch/i386/core/video_subr.c
  90. 273
    0
      src/arch/i386/core/wince_loader.c
  91. 1458
    0
      src/arch/i386/drivers/net/undi.c
  92. 178
    0
      src/arch/i386/drivers/net/undi.h
  93. 317
    0
      src/arch/i386/firmware/pcbios/basemem.c
  94. 155
    0
      src/arch/i386/firmware/pcbios/bios.c
  95. 85
    0
      src/arch/i386/firmware/pcbios/console.c
  96. 296
    0
      src/arch/i386/firmware/pcbios/e820mangler.S
  97. 94
    0
      src/arch/i386/firmware/pcbios/hidemem.c
  98. 201
    0
      src/arch/i386/firmware/pcbios/memsizes.c
  99. 45
    0
      src/arch/i386/include/bits/byteswap.h
  100. 0
    0
      src/arch/i386/include/bits/cpu.h

+ 2
- 0
src/.cvsignore View File

@@ -0,0 +1,2 @@
1
+bin
2
+gcccheck

+ 450
- 0
src/Config View File

@@ -0,0 +1,450 @@
1
+#
2
+# Config for Etherboot/32
3
+#
4
+# Do not delete the tag OptionDescription and /OptionDescription
5
+# It is used to automatically generate the documentation.
6
+#
7
+# @OptionDescription@
8
+#	User interaction options:
9
+#
10
+#	-DASK_BOOT=n
11
+#			Ask "Boot from (N)etwork ... or (Q)uit? " 
12
+#			at startup, timeout after n seconds (0 = no timeout).
13
+#			If unset or negative, don't ask and boot immediately
14
+#			using the default.
15
+#	-DBOOT_FIRST
16
+#	-DBOOT_SECOND
17
+#	-DBOOT_THIRD
18
+#			On timeout or Return key from previous
19
+#			question, selects the order to try to boot from
20
+#			various devices.
21
+#			(alternatives: BOOT_NIC, BOOT_DISK,
22
+#			 BOOT_FLOPPY, BOOT_NOTHING)
23
+#			See etherboot.h for prompt and answer strings.
24
+#			BOOT_DISK and BOOT_FLOPPY work only where a driver
25
+#			exists, e.g. in LinuxBIOS.
26
+#			They have no effect on PCBIOS.
27
+#	-DBOOT_INDEX	The device to boot from 0 == any device.
28
+#			1 == The first nic found.
29
+#			2 == The second nic found
30
+#			...
31
+#			BOOT_INDEX only applies to the BOOT_FIRST.  BOOT_SECOND 
32
+#			and BOOT_THIRD search through all of the boot devices.
33
+#	-DBAR_PROGRESS
34
+#			Use rotating bar instead of sequential dots
35
+#			to indicate an IP packet transmitted.
36
+#
37
+#	Boot order options:
38
+#
39
+#	-DBOOT_CLASS_FIRST
40
+#	-DBOOT_CLASS_SECOND
41
+#	-DBOOT_CLASS_THIRD
42
+#			Select the priority of the boot classes
43
+#			Valid values are:
44
+#				BOOT_NIC
45
+#				BOOT_DISK
46
+#				BOOT_FLOPPY
47
+#	BOOT_DISK and BOOT_FLOPPY work only where a driver exists,
48
+#	e.g. in LinuxBIOS.  They have no effect on PCBIOS.
49
+#
50
+#	Boot autoconfiguration protocol options:
51
+#
52
+#	-DALTERNATE_DHCP_PORTS_1067_1068
53
+#			Use ports 1067 and 1068 for DHCP instead of 67 and 68.
54
+#			As these ports are non-standard, you need to configure
55
+#			your DHCP server to use them. This option gets around
56
+#			existing DHCP servers which cannot be touched, for
57
+#			one reason or another, at the cost of non-standard
58
+#			boot images.
59
+#	-DNO_DHCP_SUPPORT
60
+#			Use BOOTP instead of DHCP.
61
+#	-DRARP_NOT_BOOTP
62
+#			Use RARP instead of BOOTP/DHCP.
63
+#	-DREQUIRE_VCI_ETHERBOOT
64
+#			Require an encapsulated Vendor Class Identifier
65
+#			of "Etherboot" in the DHCP reply
66
+#			Requires DHCP support.
67
+#	-DDHCP_CLIENT_ID=\"Identifier\"
68
+#	-DDHCP_CLIENT_ID_LEN=<Client ID length in octets>
69
+#	-DDHCP_CLIENT_ID_TYPE=<Client ID type>
70
+#			Specify a RFC2132 Client Identifier option, length and type.
71
+#			Requires DHCP support.
72
+#	-DDHCP_USER_CLASS=\"UserClass\"
73
+#	-DDHCP_USER_CLASS_LEN=<User Class length in octets>
74
+# 			Specify a RFC3004 User Class option and length. Use this
75
+#			option to set a UC (or multiple UCs) rather than munge the
76
+#			client Vendor Class ID.
77
+#			Requires DHCP support.
78
+#	-DALLOW_ONLY_ENCAPSULATED
79
+#			Ignore Etherboot-specific options that are not within
80
+#			the Etherboot encapsulated options field.  This option
81
+#			should be enabled unless you have a legacy DHCP server
82
+#			configuration from the bad old days before the use of
83
+#			encapsulated Etherboot options.
84
+#	-DDEFAULT_BOOTFILE=\"default_bootfile_name\"
85
+#			Define a default bootfile for the case where your DHCP
86
+#			server does not provide the information.  Example:
87
+#			  -DDEFAULT_BOOTFILE="tftp:///tftpboot/kernel"
88
+#			If you do not specify this option, then DHCP offers that
89
+#			do not specify bootfiles will be ignored.
90
+#
91
+#	NIC tuning parameters:
92
+#
93
+#	-DALLMULTI
94
+#			Turns on multicast reception in the NICs.
95
+#
96
+#	Boot tuning parameters:
97
+#
98
+#	-DCONGESTED
99
+#			Turns on packet retransmission.	 Use it on a
100
+#			congested network, where the normal operation
101
+#			can't boot the image.
102
+#	-DBACKOFF_LIMIT
103
+#			Sets the maximum RFC951 backoff exponent to n.
104
+#			Do not set this unreasonably low, because on networks
105
+#			with many machines they can saturate the link
106
+#			(the delay corresponding to the exponent is a random
107
+#			time in the range 0..3.5*2^n seconds).	Use 5 for a
108
+#			VERY small network (max. 2 minutes delay), 7 for a
109
+#			medium sized network (max. 7.5 minutes delay) or 10
110
+#			for a really huge network with many clients, frequent
111
+#			congestions (max. 1  hour delay).  On average the
112
+#			delay time will be half the maximum value.  If in
113
+#			doubt about the consequences, use a larger value.
114
+#			Also keep in mind that the number of retransmissions
115
+#			is not changed by this setting, so the default of 20
116
+#			may no longer be appropriate.  You might need to set
117
+#			MAX_ARP_RETRIES, MAX_BOOTP_RETRIES, MAX_TFTP_RETRIES
118
+#			and MAX_RPC_RETRIES to a larger value.
119
+#	-DTIMEOUT=n
120
+#			Use with care!! See above.
121
+#			Sets the base of RFC2131 sleep interval to n.
122
+#			This can be used with -DBACKOFF_LIMIT=0 to get a small
123
+#			and constant (predictable) retry interval for embedded
124
+#			devices. This is to achieve short boot delays if both
125
+#			the DHCP Server and the embedded device will be powered
126
+#			on the same time. Otherwise if the DHCP server is ready
127
+#			the client could sleep the next exponentially timeout,
128
+#			e.g. 70 seconds or more. This is not what you want.
129
+#			n should be a multiple of TICKS_PER_SEC (18).
130
+#
131
+#	Boot device options:
132
+#
133
+#	-DTRY_FLOPPY_FIRST
134
+#			If > 0, tries that many times to read the boot
135
+#			sector from a floppy drive before booting from
136
+#			ROM. If successful, does a local boot.
137
+#			It assumes the floppy is bootable.
138
+#	-DEXIT_IF_NO_OFFER
139
+#			If no IP offer is obtained, exit and
140
+#			let the BIOS continue.
141
+#			The accessibility of the TFTP server has no effect,
142
+#			so configure your DHCP/BOOTP server properly.
143
+#			You should probably reduce MAX_BOOTP_RETRIES
144
+#			to a small number like 3.
145
+#
146
+#	Boot image options:
147
+#
148
+#	-DTAGGED_IMAGE
149
+#			Add tagged image kernel boot support (recommended).
150
+#	-DAOUT_IMAGE
151
+#			Add a.out kernel boot support (generic).
152
+#	-DELF_IMAGE
153
+#			Add generic ELF kernel boot support (recommended).
154
+#	-DEL64F_IMAGE
155
+#			Add generic ELF64 kernel boot support (useful for > 4GB disks).
156
+#	-DWINCE_IMAGE
157
+#			Add the ability to boot WINCE.... now only sis630 OK!
158
+#	-DPXE_IMAGE
159
+#			Add the ability to boot PXE NBPs.  Requires
160
+#			PXE_EXPORT.  Currently not supported on
161
+#			anything other than i386
162
+#	-DFREEBSD_PXEEMU
163
+#			Add the ability to boot PXE images... only FreeBSD supported
164
+#	-DIMAGE_MULTIBOOT
165
+#			Add Multiboot image support (currently only
166
+#			for ELF images).
167
+#			Without this, generic ELF support is selected.
168
+#	-DIMAGE_FREEBSD
169
+#			Add FreeBSD image loading support (requires at least
170
+#			-DAOUT_IMAGE and/or -DELF_IMAGE).
171
+#	-DFREEBSD_KERNEL_ENV
172
+#			Pass in FreeBSD kernel environment
173
+#	-DAOUT_LYNX_KDI
174
+#			Add Lynx a.out KDI support
175
+#	-DMULTICAST_LEVEL1
176
+#			Support for sending multicast packets
177
+#	-DMULTICAST_LEVEL2
178
+#			Support for receiving multicast packets
179
+#	-DDNS_RESOLVER
180
+#			Support for resolving hostnames in bootfile name (experimental)
181
+#	-DDOWNLOAD_PROTO_TFTP
182
+#			If defined, includes TFTP support (recommended).
183
+#	-DDOWNLOAD_PROTO_NFS
184
+#			If defined, includes NFS support.
185
+#	-DDEFAULT_PROTO_NFS
186
+#			If defined, makes NFS the default protocol instead
187
+#			of TFTP. Requires DOWNLOAD_PROTO_NFS.
188
+#	-DDOWNLOAD_PROTO_SLAM
189
+#			If defined, includes Scalable Local Area Multicast
190
+#			support.
191
+#	-DDOWNLOAD_PROTO_TFTM
192
+#			If defined, includes TFTP Multicast mode support.
193
+#	-DDOWNLOAD_PROTO_HTTP
194
+#			If defined, includes HTTP support.
195
+#
196
+#	Console options:
197
+#
198
+#	-DCONSOLE_FIRMWARE
199
+#			Set for firmware/BIOS provided (default if nothing else is set).
200
+#			Normally this is shows up on your CRT.
201
+#	-DCONSOLE_SERIAL
202
+#			Set for serial console.
203
+#	-DCONSOLE_DUAL
204
+#			Both of the above
205
+#	-DCONSOLE_DIRECT_VGA
206
+#			Set for direct VGA console (only for x86).
207
+#	-DCOMCONSOLE
208
+#			Set port, e.g. 0x3F8.
209
+#	-DCONSPEED
210
+#			Set speed, e.g. 57600.
211
+#	-DCOMPARM
212
+#			Set Line Control Register value for data bits, stop
213
+#			bits and parity. See a National Semiconditor 8250/
214
+#			16450/16550 data sheet for bit meanings.
215
+#			If undefined, defaults to 0x03 = 8N1.
216
+#	-DCOMPRESERVE
217
+#			Ignore COMSPEED and COMPARAM and instead preserve
218
+#			the com port parameters from the previous user
219
+#			of the com port.  Examples of previous user are a BIOS
220
+#			that implements console redirection, lilo and LinuxBIOS.
221
+#			This makes it trivial to keep the serial port
222
+#			speed setting in sync between multiple users.
223
+#			You set the speed in the first user and the
224
+#			rest follow along.
225
+#
226
+#	Interface export options:
227
+#
228
+#	-DPXE_EXPORT
229
+#			Export a PXE API interface.  This is work in
230
+#			progress.  Note that you won't be able to load
231
+#			PXE NBPs unless you also use -DPXE_IMAGE.
232
+#	-DPXE_STRICT
233
+#			Strict(er) compliance with the PXE
234
+#			specification as published by Intel.  This may
235
+#                       or may not be a good thing depending on your
236
+#			view of the spec...
237
+#	-DPXE_DHCP_STRICT
238
+#			Strict compliance of the DHCP request packets
239
+#			with the PXE specification as published by
240
+#			Intel.  This may or may not be a good thing
241
+#			depending on your view of whether requesting
242
+#			vendor options which don't actually exist is
243
+#			pointless or not. You probably want this
244
+#			option if you intend to use Windows RIS or
245
+#			similar.
246
+#
247
+#	Obscure options you probably don't need to touch:
248
+#
249
+#	-DPOWERSAVE
250
+#			Halt the processor when waiting for keyboard input
251
+#			which saves power while waiting for user interaction.
252
+#			Good for compute clusters and VMware emulation.
253
+#			But may not work for all CPUs.
254
+#	-DBUILD_SERIAL
255
+#			Include an auto-incrementing build number in
256
+#			the Etherboot welcome message.  Useful when
257
+#			developing, to be sure that the file you
258
+#			compiled is the one you're currently testing.
259
+#	-DBUILD_ID
260
+#			Include a build ID string in the Etherboot
261
+#			welcome message.  Useful when developing, if
262
+#			you have multiple builds with different
263
+#			configurations and want to check you're
264
+#			running the one you think you are.  Requires
265
+#			-DBUILD_SERIAL.
266
+#
267
+#	BUS options:
268
+#	
269
+#	-DCONFIG_PCI
270
+#			Include support for devices using the pci bus.
271
+#	-DCONFIG_ISA
272
+#			Include support for devices using isa bus.
273
+#	-DCONFIG_PCMCIA
274
+#			Include support for PCMCIA in general *development*
275
+# @/OptionDescription@
276
+
277
+# These default settings compile Etherboot with a small number of options.
278
+# You may wish to enable more of the features if the size of your ROM allows.
279
+
280
+
281
+# Select which buses etherboot should support
282
+CFLAGS+=	-DCONFIG_PCI -DCONFIG_ISA
283
+# CFLAGS+=	-DCONFIG_PCMCIA
284
+
285
+# For prompting and default on timeout
286
+CFLAGS+=	-DASK_BOOT=3 -DBOOT_FIRST=BOOT_NIC
287
+# If you would like to attempt to boot from other devices as well as the network.
288
+# CFLAGS+=	-DBOOT_SECOND=BOOT_FLOPPY
289
+# CFLAGS+=	-DBOOT_THIRD=BOOT_DISK
290
+# CFLAGS+=	-DBOOT_INDEX=0
291
+
292
+# If you prefer the old style rotating bar progress display
293
+# CFLAGS+=	-DBAR_PROGRESS
294
+
295
+# Show size indicator
296
+# CFLAGS+=	-DSIZEINDICATOR
297
+
298
+# Enabling this creates non-standard images which use ports 1067 and 1068
299
+# for DHCP/BOOTP
300
+# CFLAGS+=	-DALTERNATE_DHCP_PORTS_1067_1068
301
+
302
+# Enabling this makes the boot ROM require a Vendor Class Identifier
303
+# of "Etherboot" in the Vendor Encapsulated Options
304
+# This can be used to reject replies from servers other than the one
305
+# we want to give out addresses to us, but it will prevent Etherboot
306
+# from getting an IP lease until you have configured DHCPD correctly
307
+# CFLAGS+=	-DREQUIRE_VCI_ETHERBOOT
308
+
309
+# EXPERIMENTAL! Set DHCP_CLIENT_ID to create a Client Identifier (DHCP
310
+# option 61, see RFC2132 section 9.14) when Etherboot sends the DHCP
311
+# DISCOVER and REQUEST packets.  This ID must UNIQUELY identify each
312
+# client on your local network.  Set DHCP_CLIENT_ID_TYPE to the
313
+# appropriate hardware type as described in RFC2132 / RFC1700; this
314
+# almost certainly means using '1' if the Client ID is an Ethernet MAC
315
+# address and '0' otherwise. Set DHCP_CLIENT_ID_LEN to the length of
316
+# the Client ID in octets (this is not a null terminated C string, do
317
+# NOT add 1 for a terminator and do NOT add an extra 1 for the
318
+# hardware type octet).  Note that to identify your client using the
319
+# normal default MAC address of your NIC, you do NOT need to set this
320
+# option, as the MAC address is automatically used in the
321
+# hwtype/chaddr field; note also that this field only sets the DHCP
322
+# option: it does NOT change the MAC address used by the client.
323
+
324
+# CFLAGS+=	-DDHCP_CLIENT_ID="'C','L','I','E','N','T','0','0','1'" \
325
+#		-DDHCP_CLIENT_ID_LEN=9 -DDHCP_CLIENT_ID_TYPE=0
326
+
327
+# CFLAGS+=	-DDHCP_CLIENT_ID="0xDE,0xAD,0xBE,0xEF,0xDE,0xAD" \
328
+#		-DDHCP_CLIENT_ID_LEN=6 -DDHCP_CLIENT_ID_TYPE=1
329
+
330
+# EXPERIMENTAL! Set DHCP_USER_CLASS to create a User Class option (see
331
+# RFC3004) when Etherboot sends the DHCP DISCOVER and REQUEST packets.
332
+# This can be used for classification of clients, typically so that a
333
+# DHCP server can send an appropriately tailored reply.  Normally, a
334
+# string identifies a class of to which this client instance belongs
335
+# which is useful in your network, such as a department ('FINANCE' or
336
+# 'MARKETING') or hardware type ('THINCLIENT' or 'KIOSK').  Set
337
+# DHCP_USER_CLASS_LEN to the length of DHCP_USER_CLASS in octets.
338
+# This is NOT a null terminated C string, do NOT add 1 for a
339
+# terminator.  RFC3004 advises how to lay out multiple User Class
340
+# options by using an octet for the length of each string, as in this
341
+# example.  It is, of course, up to the server to parse this.
342
+
343
+# CFLAGS+=	-DDHCP_USER_CLASS="'T','E','S','T','C','L','A','S','S'"	\
344
+#		-DDHCP_USER_CLASS_LEN=9
345
+
346
+# CFLAGS+=	-DDHCP_USER_CLASS="5,'A','L','P','H','A',4,'B','E','T','A'" \
347
+#		-DDHCP_USER_CLASS_LEN=11
348
+
349
+# for btext console support
350
+# CFLAGS+=	-DCONSOLE_BTEXT 
351
+# for direct PC kbd support 
352
+# CFLAGS+=	-DCONSOLE_PC_KBD
353
+# Set to enable FILO support
354
+# for FILO support it will make main call pci_init
355
+# INCLUDE_FILO=y
356
+ifdef	INCLUDE_FILO
357
+CFLAGS+=	-DCONFIG_FILO
358
+endif
359
+
360
+# Enabling this causes Etherboot to ignore Etherboot-specific options
361
+# that are not within an Etherboot encapsulated options field.
362
+# This option should be enabled unless you have a legacy DHCP server
363
+# configuration from the bad old days before the use of
364
+# encapsulated Etherboot options.
365
+CFLAGS+=	-DALLOW_ONLY_ENCAPSULATED
366
+
367
+# Disable DHCP support
368
+# CFLAGS+=	-DNO_DHCP_SUPPORT
369
+
370
+# Specify a default bootfile to be used if the DHCP server does not
371
+# provide the information.  If you do not specify this option, then
372
+# DHCP offers that do not contain bootfiles will be ignored.
373
+# CFLAGS+=	-DDEFAULT_BOOTFILE=\"tftp:///tftpboot/kernel\"
374
+
375
+# Limit the delay on packet loss/congestion to a more bearable value. See
376
+# description above.  If unset, do not limit the delay between resend.
377
+CFLAGS+=	-DBACKOFF_LIMIT=7 -DCONGESTED
378
+
379
+# More optional features
380
+# CFLAGS+=	-DTRY_FLOPPY_FIRST=4
381
+# CFLAGS+=	-DEXIT_IF_NO_OFFER
382
+
383
+# For a serial console, which can run in parallel with FIRMWARE console
384
+# CFLAGS+=	-DCONSOLE_DUAL -DCOMCONSOLE=0x3F8 -DCONSPEED=9600
385
+
386
+# Enable tagged image, generic ELF, Multiboot ELF
387
+# or FreeBSD ELF/a.out boot image support
388
+CFLAGS+=	-DTAGGED_IMAGE -DELF_IMAGE
389
+# CFLAGS+=	-DAOUT_IMAGE -DIMAGE_MULTIBOOT -DIMAGE_FREEBSD
390
+# CFLAGS+=	-DAOUT_IMAGE -DAOUT_LYNX_KDI
391
+# CFLAGS+=	-DCOFF_IMAGE 
392
+# CFLAGS+=	-DRAW_IMAGE
393
+
394
+# Download files via TFTP
395
+CFLAGS+=	-DDOWNLOAD_PROTO_TFTP
396
+# Change download protocol to NFS, default is TFTP
397
+# CFLAGS+=	-DDOWNLOAD_PROTO_NFS
398
+# Change download protocol to HTTP, default is TFTP
399
+# CFLAGS+=	-DDOWNLOAD_PROTO_HTTP
400
+# Change default protocol to NFS
401
+# CFLAGS+=	-DDEFAULT_PROTO_NFS
402
+# Support to resolve hostnames in boot filename
403
+# CFLAGS+=	-DDNS_RESOLVER
404
+
405
+# Multicast Support
406
+# CFLAGS+=	-DALLMULTI -DMULTICAST_LEVEL1 -DMULTICAST_LEVEL2 -DDOWNLOAD_PROTO_TFTM
407
+
408
+# Etherboot as a PXE network protocol ROM
409
+CFLAGS+=	-DPXE_IMAGE -DPXE_EXPORT
410
+# Etherboot stricter as a PXE network protocol ROM
411
+# CFLAGS+=	-DPXE_DHCP_STRICT
412
+
413
+# Support for PXE emulation. Works only with FreeBSD to load the kernel
414
+# via pxeboot, use only with DOWNLOAD_PROTO_NFS
415
+# CFLAGS+=	-DFREEBSD_PXEEMU
416
+
417
+# Include an auto-incrementing build serial number and optional build
418
+# ID string
419
+# CFLAGS+=	-DBUILD_SERIAL
420
+# CFLAGS+=	-DBUILD_SERIAL -DBUILD_ID=\"testing\"
421
+
422
+# Do not relocate
423
+# core/relocate.c should really be moved to an arch specific directory
424
+# but this is here for archs that don't support relocation
425
+# CFLAGS+=	-DNORELOCATE
426
+
427
+# you should normally not need to change these
428
+HOST_CC=	gcc
429
+CPP=		gcc -E -Wp,-Wall
430
+RM=		rm -f
431
+TOUCH=		touch
432
+PERL=		/usr/bin/perl
433
+CC=		gcc
434
+AS=		as
435
+LD=		ld
436
+SIZE=		size
437
+AR=		ar
438
+RANLIB=		ranlib
439
+OBJCOPY=	objcopy
440
+
441
+CFLAGS+=	-Os -ffreestanding
442
+CFLAGS+=	-Wall -W -Wno-format
443
+CFLAGS+=	$(EXTRA_CFLAGS)
444
+ASFLAGS+=	$(EXTRA_ASFLAGS)
445
+LDFLAGS+=	$(EXTRA_LDFLAGS)
446
+# For debugging
447
+# LDFLAGS+=	-Map $@.map
448
+
449
+# Location to place generated binaries, and files
450
+BIN=bin

+ 133
- 0
src/Families View File

@@ -0,0 +1,133 @@
1
+# This is the config file for creating Makefile rules for Etherboot ROMs
2
+#
3
+# To make a ROM for a supported NIC locate the appropriate family
4
+# and add a line of the form
5
+#
6
+# ROM		PCI-IDs		Comment
7
+#
8
+# ROM is the desired output name for both .rom and .lzrom images.
9
+# PCI IDs are the PCI vendor and device IDs of the PCI NIC
10
+# For ISA NICs put -
11
+#
12
+# All PCI ROMs that share a single driver are only built once (because they
13
+# only have different PCI-IDs, but identical code).  ISA ROMS are built for
14
+# each ROM type, because different vendors used a different logic around the
15
+# basic chip.  The most popular example is the NS8390, which some cards use
16
+# in PIO mode, some in DMA mode.  Two chips currently don't fit into this nice
17
+# black-and-white scheme (the Lance and the NS8390).  Their driver deals
18
+# with both PCI and ISA cards.  These drivers will be treated similarly to
19
+# ISA only drivers by genrules.pl and are compiled for each ROM type that is
20
+# ISA, and additionally compiled for the PCI card type.
21
+#
22
+# Then do: make clean, make Roms and make
23
+#
24
+# Please send additions to this file to <kenUNDERSCOREyap AT users PERIOD sourceforge PERIOD net>
25
+
26
+# Start of configuration
27
+
28
+family		drivers/net/skel
29
+
30
+family		arch/ia64/drivers/net/undi_nii
31
+undi_nii	-
32
+
33
+# 3c59x cards (Vortex) and 3c900 cards
34
+# If your 3c900 NIC detects but fails to work, e.g. no link light, with
35
+# the 3c90x driver, try using the 3c595 driver. I have one report that the
36
+# 3c595 driver handles these NICs properly. (The 595 driver uses the
37
+# programmed I/O mode of operation, whereas the 90x driver uses the bus
38
+# mastering mode. These NICs are capable of either mode.) When it comes to
39
+# making a ROM, as usual, you must choose the correct image, the one that
40
+# contains the same PCI IDs as your NIC.
41
+family		drivers/net/3c595
42
+
43
+# 3Com 3c90x cards
44
+family		drivers/net/3c90x
45
+
46
+# Intel Etherexpress Pro/100
47
+family		drivers/net/eepro100
48
+
49
+#Intel Etherexpress Pro/1000
50
+family		drivers/net/e1000
51
+
52
+#Broadcom Tigon 3
53
+family		drivers/net/tg3
54
+
55
+family		drivers/net/pcnet32
56
+
57
+# National Semiconductor ns83820 (Gigabit) family
58
+family		drivers/net/ns83820
59
+
60
+family		drivers/net/tulip
61
+
62
+family		drivers/net/davicom
63
+
64
+family		drivers/net/rtl8139
65
+
66
+family		drivers/net/r8169
67
+
68
+family		drivers/net/via-rhine
69
+
70
+family		drivers/net/w89c840
71
+
72
+family		drivers/net/sis900
73
+
74
+family		drivers/net/natsemi
75
+
76
+family		drivers/net/prism2_plx
77
+
78
+family		drivers/net/prism2_pci
79
+# Various Prism2.5 (PCI) devices that manifest themselves as Harris Semiconductor devices
80
+# (with the actual vendor appearing as the vendor of the first subsystem)
81
+hwp01170	0x1260,0x3873	ActionTec HWP01170
82
+dwl520		0x1260,0x3873	DLink DWL-520
83
+
84
+family		drivers/net/ns8390
85
+wd		-		WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)
86
+ne		-		NE1000/2000 and clones
87
+3c503		-		3Com503, Etherlink II[/16]
88
+
89
+family		drivers/net/epic100
90
+
91
+family		drivers/net/3c509
92
+3c509		-		3c509, ISA/EISA
93
+3c529		-		3c529 == MCA 3c509
94
+
95
+family		drivers/net/3c515
96
+3c515		-		3c515, Fast EtherLink ISA
97
+
98
+family		drivers/net/eepro
99
+eepro		-		Intel Etherexpress Pro/10
100
+
101
+family		drivers/net/cs89x0
102
+cs89x0		-		Crystal Semiconductor CS89x0
103
+
104
+family		drivers/net/depca
105
+depca		-		Digital DE100 and DE200
106
+
107
+family          drivers/net/forcedeth
108
+
109
+family		drivers/net/sk_g16
110
+sk_g16		-		Schneider and Koch G16
111
+
112
+family		drivers/net/smc9000
113
+smc9000		-		SMC9000
114
+
115
+family		drivers/net/sundance
116
+
117
+family		drivers/net/tlan
118
+
119
+family		drivers/disk/ide_disk
120
+ide_disk	0x0000,0x0000	Generic IDE disk support
121
+
122
+family		drivers/disk/pc_floppy
123
+
124
+family		arch/i386/drivers/net/undi
125
+undi		0x0000,0x0000	UNDI driver support
126
+
127
+family		drivers/net/pnic
128
+
129
+family		arch/armnommu/drivers/net/p2001_eth
130
+
131
+family		drivers/net/mtd80x
132
+
133
+family		drivers/net/dmfe

+ 15
- 0
src/Makefile View File

@@ -0,0 +1,15 @@
1
+# Override ARCH here or on the command line
2
+# ARCH=i386
3
+# Additionally you can supply extra compilation arguments, e.g. for x86_64
4
+# EXTRA_CFLAGS=-m32
5
+# EXTRA_ASFLAGS=--32
6
+# EXTRA_LDFLAGS=-m elf_i386
7
+ifndef ARCH
8
+ARCH:=$(shell uname -m | sed -e s,i[3456789]86,i386,)
9
+endif
10
+MAKEDEPS:=
11
+SUFFIXES:=
12
+
13
+include Config
14
+include arch/$(ARCH)/Config
15
+include Makefile.main

+ 18
- 0
src/Makefile-armnommu View File

@@ -0,0 +1,18 @@
1
+ARCH:=armnommu
2
+MAKEDEPS:=
3
+
4
+include Config
5
+include arch/$(ARCH)/Config
6
+
7
+CC=		$(CROSS_COMPILE)gcc
8
+AS=		$(CROSS_COMPILE)as
9
+LD=		$(CROSS_COMPILE)ld
10
+SIZE=		$(CROSS_COMPILE)size
11
+AR=		$(CROSS_COMPILE)ar
12
+RANLIB=		$(CROSS_COMPILE)ranlib
13
+OBJCOPY=	$(CROSS_COMPILE)objcopy
14
+
15
+MAKEDEPS+=Makefile-armnommu
16
+BIN=bin
17
+
18
+include Makefile.main

+ 18
- 0
src/Makefile-e1 View File

@@ -0,0 +1,18 @@
1
+ARCH:=e1
2
+MAKEDEPS:=
3
+
4
+include arch/$(ARCH)/Config
5
+include Config
6
+
7
+CC=		e1-coff-gcc
8
+AS=		e1-coff-as
9
+LD=		e1-coff-ld
10
+SIZE=	e1-coff-size
11
+AR=		e1-coff-ar
12
+RANLIB=	e1-coff-ranlib
13
+OBJCOPY=e1-coff-objcopy
14
+
15
+MAKEDEPS+=Makefile-e1
16
+BIN=bin-e1
17
+
18
+include Makefile.main

+ 18
- 0
src/Makefile-i386 View File

@@ -0,0 +1,18 @@
1
+ARCH:=i386
2
+MAKEDEPS:=
3
+
4
+include arch/$(ARCH)/Config
5
+include Config
6
+
7
+CC=		i386-linux-gcc
8
+AS=		i386-linux-as
9
+LD=		i386-linux-ld
10
+SIZE=		i386-linux-size
11
+AR=		i386-linux-ar
12
+RANLIB=		i386-linux-ranlib
13
+OBJCOPY=	i386-linux-objcopy
14
+
15
+MAKEDEPS+=Makefile-i386
16
+BIN=bin-i386
17
+
18
+include Makefile.main

+ 18
- 0
src/Makefile-ia64 View File

@@ -0,0 +1,18 @@
1
+ARCH:=ia64
2
+MAKEDEPS:=
3
+
4
+include arch/$(ARCH)/Config
5
+include Config
6
+
7
+CC=		ia64-linux-gcc
8
+AS=		ia64-linux-as
9
+LD=		ia64-linux-ld
10
+SIZE=		ia64-linux-size
11
+AR=		ia64-linux-ar
12
+RANLIB=		ia64-linux-ranlib
13
+OBJCOPY=	ia64-linux-objcopy
14
+
15
+MAKEDEPS+=Makefile-ia64
16
+BIN=bin-ia64
17
+
18
+include Makefile.main

+ 450
- 0
src/Makefile.main View File

@@ -0,0 +1,450 @@
1
+#
2
+# Makefile for Etherboot
3
+#
4
+# Most of the time you should edit Config
5
+#
6
+# Common options:
7
+#	VERSION_*=v	- Set the major and minor version numbers
8
+#
9
+# NS8390 options:
10
+#	-DINCLUDE_NE	- Include NE1000/NE2000 support
11
+#	-DNE_SCAN=list	- Probe for NE base address using list of
12
+#			  comma separated hex addresses
13
+#	-DINCLUDE_3C503 - Include 3c503 support
14
+#	  -DT503_SHMEM	- Use 3c503 shared memory mode (off by default)
15
+#	-DINCLUDE_WD	- Include Western Digital/SMC support
16
+#	-DWD_DEFAULT_MEM- Default memory location for WD/SMC cards
17
+#	-DWD_790_PIO    - Read/write to WD/SMC 790 cards in PIO mode (default
18
+#			  is to use shared memory) Try this if you get "Bogus
19
+#			  packet, ignoring" messages, common on ISA/PCI hybrid
20
+#			  systems.
21
+#	-DCOMPEX_RL2000_FIX
22
+#
23
+#	If you have a Compex RL2000 PCI 32-bit (11F6:1401),
24
+#	and the bootrom hangs in "Probing...[NE*000/PCI]",
25
+#	try enabling this fix... it worked for me :).
26
+#	In the first packet write somehow it somehow doesn't
27
+#	get back the expected data so it is stuck in a loop.
28
+#	I didn't bother to investigate what or why because it works
29
+#	when I interrupt the loop if it takes more then COMPEX_RL2000_TRIES.
30
+#	The code will notify if it does a abort.
31
+#	SomniOne - somnione@gmx.net
32
+#
33
+# 3C509 option:
34
+#	-DINCLUDE_3C509	- Include 3c509 support
35
+#
36
+# 3C90X options:
37
+#	-DINCLUDE_3C90X	- Include 3c90x support
38
+#
39
+#	Warning Warning Warning
40
+#	If you use any of the XCVR options below, please do not complain about
41
+#	the behaviour with Linux drivers to the kernel developers. You are
42
+#	on your own if you do this. Please read 3c90x.txt to understand
43
+#	what they do. If you don't understand them, ask for help on the
44
+#	Etherboot mailing list. And please document what you did to the NIC
45
+#	on the NIC so that people after you won't get nasty surprises.
46
+#
47
+#	-DCFG_3C90X_PRESERVE_XCVR - Reset the transceiver type to the value it
48
+#			  had initially just before the loaded code is started.
49
+#	-DCFG_3C90X_XCVR - Hardcode the tranceiver type Etherboot uses.
50
+#	-DCFG_3C90X_BOOTROM_FIX - If you have a 3c905B with buggy ROM
51
+#			  interface, setting this option might "fix" it.  Use
52
+#			  with caution and read the docs in 3c90x.txt!
53
+#
54
+#	See the documentation file 3c90x.txt for more details.
55
+#
56
+# CS89X0 (optional) options:
57
+#	-DINCLUDE_CS89X0- Include CS89x0 support
58
+#	-DCS_SCAN=list	- Probe for CS89x0 base address using list of
59
+#			  comma separated hex addresses; increasing the
60
+#			  address by one (0x300 -> 0x301) will force a
61
+#			  more aggressive probing algorithm. This might
62
+#			  be neccessary after a soft-reset of the NIC.
63
+#
64
+# LANCE options:
65
+#	-DINCLUDE_NE2100- Include NE2100 support
66
+#	-DINCLUDE_NI6510- Include NI6510 support
67
+#
68
+# SK_G16 options:
69
+#	-DINCLUDE_SK_G16- Include SK_G16 support
70
+#
71
+# I82586 options:
72
+#	-DINCLUDE_3C507	- Include 3c507 support
73
+#	-DINCLUDE_NI5210- Include NI5210 support
74
+#	-DINCLUDE_EXOS205-Include EXOS205 support
75
+#
76
+# SMC9000 options:
77
+#       -DINCLUDE_SMC9000   - Include SMC9000 driver
78
+#       -DSMC9000_SCAN=list - List of I/O addresses to probe
79
+#
80
+# TIARA (Fujitsu Etherstar) options:
81
+#	-DINCLUDE_TIARA	- Include Tiara support
82
+#
83
+# NI5010 options:
84
+#	-DINCLUDE_NI5010 - Include NI5010 support
85
+#
86
+# TULIP options:
87
+#	-DINCLUDE_TULIP	- Include Tulip support
88
+#
89
+# RTL8139 options:
90
+#	-DINCLUDE_RTL8139 - Include RTL8139 support
91
+#
92
+# SIS900 options:
93
+#	-DINCLUDE_SIS900 - Include SIS900 support
94
+#
95
+# NATSEMI options:
96
+#	-DINCLUDE_NATSEMI - Include NATSEMI support
97
+#
98
+
99
+SRCS:=
100
+BOBJS:=
101
+
102
+MAKEROM=	$(PERL) ./util/makerom.pl
103
+VERSION_MAJOR=	5
104
+VERSION_MINOR=	3
105
+VERSION_PATCH=	14
106
+EXTRAVERSION=	
107
+VERSION=	$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)$(EXTRAVERSION)
108
+MM_VERSION=	$(VERSION_MAJOR).$(VERSION_MINOR)
109
+CFLAGS+=	-DVERSION_MAJOR=$(VERSION_MAJOR) \
110
+		-DVERSION_MINOR=$(VERSION_MINOR) \
111
+		-DVERSION=\"$(VERSION)\" $(OLDGAS) \
112
+		-I include -I arch/$(ARCH)/include \
113
+		-DARCH=$(ARCH)
114
+FILO=filo
115
+FILO_PROGRAM_NAME = FILO
116
+FILO_PROGRAM_VERSION = 0.4.1
117
+FILO_BUILD_INFO = ($(shell whoami)@$(shell hostname)) $(shell LANG=C date)
118
+
119
+GCCINCDIR = $(shell $(CC) -print-search-dirs | head -n 1 | cut -d' ' -f2)include
120
+CPPFLAGS = -nostdinc -imacros filo/config.h 
121
+#-Ifilo/include -I$(GCCINCDIR) -MD
122
+ASFLAGS_X = -D__ASSEMBLY__
123
+
124
+IDENT=		'$(@F) $(VERSION) (GPL) etherboot.org'
125
+
126
+# Find out if we're using binutils 2.9.1 which uses a different syntax in some
127
+# places (most prominently in the opcode prefix area).
128
+OLDGAS:=	$(shell $(AS) --version | grep -q '2\.9\.1' && echo -DGAS291)
129
+
130
+BUILD_LIBS=	$(BLIB)
131
+BUILD_IMGS=	$(IMGS)
132
+
133
+3C503FLAGS=	-DINCLUDE_3C503 # -DT503_SHMEM
134
+# Note that the suffix to MAKEROM_ is the (mixed case) basename of the ROM file
135
+MAKEROM_3c503=	-3
136
+3C507FLAGS=	-DINCLUDE_3C507
137
+3C509FLAGS=	-DINCLUDE_3C509
138
+3C529FLAGS=	-DINCLUDE_3C529
139
+3C595FLAGS=	-DINCLUDE_3C595
140
+3C90XFLAGS=	-DINCLUDE_3C90X
141
+CS89X0FLAGS=	-DINCLUDE_CS89X0
142
+EEPROFLAGS=	-DINCLUDE_EEPRO
143
+EEPRO100FLAGS=	-DINCLUDE_EEPRO100
144
+E1000FLAGS=	-DINCLUDE_E1000
145
+EPIC100FLAGS=	-DINCLUDE_EPIC100
146
+EXOS205FLAGS=	-DINCLUDE_EXOS205
147
+LANCEFLAGS=	-DINCLUDE_LANCE		# Lance/PCI!
148
+NE2100FLAGS=	-DINCLUDE_NE2100
149
+NEFLAGS=	-DINCLUDE_NE -DNE_SCAN=0x300,0x280,0x320,0x340,0x380
150
+NS8390FLAGS=	-DINCLUDE_NS8390	# NE2000/PCI!
151
+NI5010FLAGS=	-DINCLUDE_NI5010
152
+NI5210FLAGS=	-DINCLUDE_NI5210
153
+NI6510FLAGS=	-DINCLUDE_NI6510
154
+RTL8139FLAGS=	-DINCLUDE_RTL8139
155
+SK_G16FLAGS=	-DINCLUDE_SK_G16
156
+SIS900FLAGS=   	-DINCLUDE_SIS900
157
+NATSEMIFLAGS=  	-DINCLUDE_NATSEMI
158
+SMC9000FLAGS=   -DINCLUDE_SMC9000
159
+SUNDANCEFLAGS=	-DINCLUDE_SUNDANCE
160
+TLANFLAGS=	-DINCLUDE_TLAN
161
+TIARAFLAGS=	-DINCLUDE_TIARA
162
+DEPCAFLAGS=	-DINCLUDE_DEPCA	# -DDEPCA_MODEL=DEPCA -DDEPCA_RAM_BASE=0xd0000
163
+TULIPFLAGS=	-DINCLUDE_TULIP
164
+OTULIPFLAGS=	-DINCLUDE_OTULIP
165
+VIA_RHINEFLAGS=	-DINCLUDE_VIA_RHINE
166
+WDFLAGS=	-DINCLUDE_WD -DWD_DEFAULT_MEM=0xCC000
167
+W89C840FLAGS=	-DINCLUDE_W89C840
168
+
169
+SRCS+=	core/serial.c
170
+
171
+SRCS+=	core/btext.c core/pc_kbd.c
172
+
173
+SRCS+=	core/main.c core/pci.c core/osloader.c core/nfs.c
174
+SRCS+=	core/misc.c core/config.c core/isa_probe.c core/pci_probe.c
175
+SRCS+=	core/relocate.c core/heap.c
176
+SRCS+=	drivers/disk/floppy.c core/nic.c core/disk.c core/timer.c
177
+SRCS+=	core/proto_eth_slow.c
178
+SRCS+=	core/proto_slam.c core/proto_tftm.c core/proto_http.c
179
+SRCS+=	core/isapnp.c
180
+SRCS+=	core/pcmcia.c core/i82365.c
181
+SRCS+=	core/pxe_export.c core/dns_resolver.c
182
+
183
+FILO_SRCS+=	$(FILO)/drivers/ide_x.c  
184
+FILO_SRCS+=	$(FILO)/fs/blockdev.c $(FILO)/fs/eltorito.c $(FILO)/fs/fsys_ext2fs.c $(FILO)/fs/fsys_fat.c $(FILO)/fs/fsys_iso9660.c
185
+FILO_SRCS+=	$(FILO)/fs/fsys_reiserfs.c $(FILO)/fs/vfs.c $(FILO)/fs/fsys_jfs.c $(FILO)/fs/fsys_minix.c $(FILO)/fs/fsys_xfs.c  
186
+FILO_SRCS+=	$(FILO)/main/elfload.c $(FILO)/main/elfnote.c $(FILO)/main/filo_x.c $(FILO)/main/lib.c $(FILO)/main/linuxbios_x.c 
187
+FILO_SRCS+=	$(FILO)/main/pci_x.c $(FILO)/main/malloc_x.c $(FILO)/main/printf_x.c $(FILO)/main/console_x.c 
188
+FILO_SRCS+=	$(FILO)/$(ARCH)/context.c $(FILO)/$(ARCH)/linux_load.c $(FILO)/$(ARCH)/segment.c $(FILO)/$(ARCH)/sys_info.c 
189
+FILO_SRCS+=	$(FILO)/$(ARCH)/switch.S $(FILO)/usb/debug_x.c $(FILO)/usb/scsi_cmds.c $(FILO)/usb/uhci.c $(FILO)/usb/usb.c 
190
+FILO_SRCS+=	$(FILO)/usb/ohci.c $(FILO)/usb/usb_scsi_low.c  $(FILO)/usb/usb_x.c
191
+
192
+
193
+BOBJS+=		$(BIN)/main.o $(BIN)/osloader.o $(BIN)/nfs.o $(BIN)/misc.o
194
+BOBJS+=		$(BIN)/proto_slam.o $(BIN)/proto_tftm.o $(BIN)/proto_http.o
195
+BOBJS+=		$(BIN)/floppy.o
196
+BOBJS+=		$(BIN)/serial.o $(BIN)/timer.o  $(BIN)/relocate.o $(BIN)/heap.o
197
+BOBJS+=		$(BIN)/btext.o $(BIN)/pc_kbd.o
198
+BOBJS+=		$(BIN)/nic.o $(BIN)/disk.o
199
+BOBJS+=		$(BIN)/isapnp.o
200
+BOBJS+=		$(BIN)/pci.o $(BIN)/isa_probe.o $(BIN)/pci_probe.o
201
+BOBJS+=		$(BIN)/vsprintf.o $(BIN)/string.o
202
+BOBJS+=		$(BIN)/pcmcia.o $(BIN)/i82365.o
203
+BOBJS+=		$(BIN)/pxe_export.o $(BIN)/dns_resolver.o
204
+
205
+FILO_OBJS+=		$(BIN)/ide_x.o $(BIN)/pci_x.o
206
+FILO_OBJS+=		$(BIN)/blockdev.o $(BIN)/eltorito.o $(BIN)/fsys_ext2fs.o $(BIN)/fsys_fat.o $(BIN)/fsys_iso9660.o $(BIN)/fsys_reiserfs.o $(BIN)/vfs.o
207
+FILO_OBJS+=		$(BIN)/fsys_jfs.o $(BIN)/fsys_minix.o $(BIN)/fsys_xfs.o  
208
+FILO_OBJS+=		$(BIN)/elfload.o  $(BIN)/elfnote.o  $(BIN)/filo_x.o $(BIN)/lib.o $(BIN)/linuxbios_x.o $(BIN)/malloc_x.o $(BIN)/printf_x.o $(BIN)/console_x.o   
209
+FILO_OBJS+=		$(BIN)/context.o  $(BIN)/linux_load.o  $(BIN)/segment.o  $(BIN)/sys_info.o $(BIN)/switch.o
210
+FILO_OBJS+=		$(BIN)/debug_x.o  $(BIN)/scsi_cmds.o $(BIN)/uhci.o $(BIN)/usb.o $(BIN)/ohci.o $(BIN)/usb_scsi_low.o $(BIN)/usb_x.o
211
+
212
+BLIB=		$(BIN)/bootlib.a 
213
+FILOLIB=	$(BIN)/filolib.a
214
+LIBS=		$(BLIB)
215
+ifdef	INCLUDE_FILO
216
+LIBS+=		$(FILOLIB)
217
+endif
218
+UTILS+=		$(BIN)/nrv2b
219
+STDDEPS=	$(START) $(UTILS)
220
+# MAKEDEPS is the one target that is depended by all ROMs, so we check gcc here
221
+# If you are confident that gcc 2.96 works for you, you can remove the lines
222
+# that check gcc in the toolcheck rule
223
+MAKEDEPS+=	Makefile Makefile.main Config genrules.pl Families
224
+MAKEDEPS+=	$(BIN)/toolcheck
225
+MAKEDEPS+=	arch/$(ARCH)/Makefile arch/$(ARCH)/Config
226
+
227
+# Start of targets
228
+
229
+.PHONY:	noargs
230
+noargs:	$(BIN)/toolcheck
231
+	@echo '===================================================='
232
+	@echo 'No target specified. To specify a target, do: '
233
+	@echo
234
+	@echo '    $(MAKE) bin/<rom-name>.<output-format> '
235
+	@echo
236
+	@echo 'where <output-format> is one of {zdsk, zrom, iso, liso, zlilo, zpxe, elf, com}'
237
+	@echo
238
+	@echo 'or: '
239
+	@echo
240
+	@echo '    $(MAKE) all<output-format>s'
241
+	@echo
242
+	@echo 'to generate all possible images of format <output-format>'
243
+	@echo
244
+	@echo 'For example, '
245
+	@echo
246
+	@echo '    make allzroms '
247
+	@echo
248
+	@echo 'will generate all possible .zrom (rom burnable) images, and'
249
+	@echo
250
+	@echo '    make allzdsks'
251
+	@echo
252
+	@echo 'will generate all possible .zdsk (bootable floppy) images, or'
253
+	@echo
254
+	@echo '===================================================='
255
+	@exit 1
256
+
257
+$(BIN)/toolcheck:	Makefile Config
258
+	@if $(CC) -v 2>&1 | grep -is 'gcc version 2\.96' > /dev/null; \
259
+	then \
260
+		echo 'gcc 2.96 is unsuitable for compiling Etherboot'; \
261
+		echo 'Use gcc 2.95 or gcc 3.x instead'; \
262
+		exit 1; \
263
+	else \
264
+		touch $(BIN)/toolcheck; \
265
+	fi; \
266
+	if [ `perl -e 'use bytes; print chr(255)' | wc -c` = 2 ]; \
267
+	then \
268
+		echo 'Your Perl version has a Unicode handling bug'; \
269
+		echo 'To workaround, execute this before compiling Etherboot:'; \
270
+		echo 'export LANG=$${LANG%.UTF-8}'; \
271
+		exit 1; \
272
+	fi
273
+
274
+include		arch/$(ARCH)/Makefile
275
+
276
+# Common files
277
+
278
+$(BLIB):	$(BOBJS)
279
+	$(AR) r $@ $(BOBJS)
280
+	$(RANLIB) $@
281
+
282
+$(FILOLIB):	$(FILO_OBJS)
283
+	$(AR) r $@ $(FILO_OBJS)
284
+	$(RANLIB) $@
285
+
286
+# LinuxBIOS support code
287
+$(BIN)/linuxbios.o:	firmware/linuxbios/linuxbios.c include/etherboot.h include/dev.h firmware/linuxbios/linuxbios_tables.h
288
+
289
+# Do not add driver specific dependencies here unless it's something the
290
+# genrules.pl script *can't* deal with, i.e. if it is not C code.
291
+
292
+$(FILO)/config.h: $(FILO)/Config
293
+	/bin/echo -e '/* GENERATED FILE, DO NOT EDIT */\n' >$@
294
+	sed -e 's/#.*//' -e '/=/!d' -e 's/\([^[:space:]]*\)[[:space:]]*=[[:space:]]*\(.*\).*/#define \1 \2/' -e 's/^#define \([^ ]*\) 0$$/#undef \1/' $^ >>$@
295
+
296
+filo_version: $(FILO)/main/version.h
297
+
298
+$(FILO)/main/version.h: FORCE
299
+	echo '#define PROGRAM_NAME "$(FILO_PROGRAM_NAME)"' > $@
300
+	echo '#define PROGRAM_VERSION "$(FILO_PROGRAM_VERSION) $(FILO_BUILD_INFO)"' >> $@
301
+
302
+FORCE:
303
+
304
+
305
+# Utilities
306
+
307
+$(BIN)/lzhuf:	util/lzhuf.c
308
+	$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -o $@ $<
309
+
310
+# Roms file
311
+# Builds almost silently because this rule is triggered for just about
312
+# every modification to sources.
313
+
314
+$(BIN)/Roms $(BIN)/NIC:	genrules.pl Families $(SRCS)
315
+	@mkdir -p $(@D)
316
+	@echo Scanning for ROMs and dependencies...
317
+	@$(PERL) ./genrules.pl Families $(BIN)/NIC $(ARCH) $(SRCS) > $(BIN)/Roms
318
+
319
+# Pattern Rules
320
+
321
+# general rules for compiling/assembling source files
322
+$(BIN)/%.o:	core/%.c $(MAKEDEPS)
323
+	$(CC) $(CFLAGS) -o $@ -c $<
324
+
325
+$(BIN)/%.s:	core/%.c $(MAKEDEPS)
326
+	$(CC) $(CFLAGS) -S -o $@ -c $<
327
+
328
+$(BIN)/%.o:	drivers/disk/%.c $(MAKEDEPS)
329
+	$(CC) $(CFLAGS) -o $@ -c $<
330
+
331
+$(BIN)/%.o:	drivers/net/%.c $(MAKEDEPS)
332
+	$(CC) $(CFLAGS) -o $@ -c $<
333
+
334
+$(BIN)/%.o:	firmware/linuxbios/%.c $(MAKEDEPS)
335
+	$(CC) $(CFLAGS) -o $@ -c $<
336
+
337
+$(BIN)/%.o:     $(FILO)/drivers/%.c $(MAKEDEPS) $(FILO)/config.h
338
+	$(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
339
+
340
+$(BIN)/%.o:     $(FILO)/fs/%.c $(MAKEDEPS) $(FILO)/config.h
341
+	$(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
342
+
343
+$(BIN)/%.o:     $(FILO)/$(ARCH)/%.c $(MAKEDEPS) $(FILO)/config.h
344
+	$(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
345
+
346
+$(BIN)/%.o:     $(FILO)/$(ARCH)/%.S $(MAKEDEPS) $(FILO)/config.h
347
+	$(CC) $(ASFLAGS_X) $(CPPFLAGS) -c $< -o $@
348
+
349
+$(BIN)/%.o:     $(FILO)/main/%.c $(MAKEDEPS) $(FILO)/config.h filo_version
350
+	$(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
351
+
352
+$(BIN)/%.o:     $(FILO)/usb/%.c $(MAKEDEPS) $(FILO)/config.h
353
+	$(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
354
+
355
+# Rule for the super etherboot image.
356
+$(BIN)/etherboot.o: $(DOBJS)
357
+	$(LD) $(LDFLAGS) -r $(DOBJS) -o $@
358
+
359
+$(BIN)/etherboot-pci.o: $(PCIOBJS)
360
+	$(LD) $(LDFLAGS) -r $(PCIOBJS) -o $@
361
+
362
+# General rules for generating runtime (rt) files
363
+$(BIN)/%.rt.o:  $(BIN)/%.o $(START) $(BIN)/config.o $(LIBS) $(STDDEPS) $(MAKEDEPS)
364
+	$(LD) $(LDFLAGS) -r $(START) $(BIN)/config.o $< $(LIBS) -o $@
365
+
366
+#   Rule for $(BIN)/%.FORMAT.rt is architecture and target-format specific
367
+
368
+$(BIN)/%.rt.bin: $(BIN)/%.rt $(MAKEDEPS)
369
+	$(OBJCOPY) -O binary -R .prefix $< $@
370
+
371
+$(BIN)/%.rt1.bin: $(BIN)/%.rt $(MAKEDEPS)
372
+	$(OBJCOPY) -O binary -j .text.nocompress $< $@
373
+
374
+$(BIN)/%.rt2.bin: $(BIN)/%.rt $(MAKEDEPS)
375
+	$(OBJCOPY) -O binary -R .prefix -R .text.nocompress $< $@
376
+
377
+# Rules for generating prefix binary files
378
+
379
+#   Rule for $(BIN)/%.FORMAT.prf is architecture and target-format specific
380
+$(BIN)/%.prf.bin: $(BIN)/%.prf $(MAKEDEPS)
381
+	$(OBJCOPY) -j .prefix -O binary $< $@
382
+
383
+# general rule for .z (compressed binary code), may be overridden
384
+$(BIN)/%.zbin: $(BIN)/%.bin $(BIN)/nrv2b $(MAKEDEPS)
385
+	$(BIN)/nrv2b e $< $@
386
+
387
+# Housekeeping
388
+
389
+clean:
390
+	$(RM) $(BIN)/*
391
+	$(RM) $(FILO)/config.h $(FILO)/main/version.h
392
+
393
+../index.html:	../index.xhtml
394
+	(cd ..; m4 -P -DHOSTSITE=SOURCEFORGE index.xhtml > index.html)
395
+
396
+../index-berlios.html:	../index.xhtml
397
+	(cd ..; m4 -P -DHOSTSITE=BERLIOS index.xhtml > index-berlios.html)
398
+
399
+tarball: ../index.html ../index-berlios.html
400
+	(echo -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION
401
+	(cd ../..; tar cf /tmp/etherboot-$(VERSION).tar --exclude CVS --exclude doc etherboot-$(VERSION))
402
+	bzip2 -9 < /tmp/etherboot-$(VERSION).tar > /tmp/etherboot-$(VERSION).tar.bz2
403
+	gzip -9 < /tmp/etherboot-$(VERSION).tar > /tmp/etherboot-$(VERSION).tar.gz
404
+
405
+# Auto-incrementing build serial number.  Is auto-incremented for each
406
+# make run that specifies a final image file (e.g. bin/undi.zpxe) as a
407
+# target, or a target of the form "all*".  Enable via -DBUILD_SERIAL
408
+# in Config.
409
+
410
+ifneq ($(findstring -DBUILD_SERIAL,$(CFLAGS)),)
411
+
412
+# If no make goals are specified, it means "make all"
413
+REALGOALS = $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all)
414
+
415
+# Filter to see if there are any targets to trigger an auto-increment
416
+BUILDGOALS = $(filter all,$(REALGOALS)) $(filter all%,$(REALGOALS)) \
417
+	     $(foreach SUFFIX,$(SUFFIXES),$(filter %.$(SUFFIX),$(REALGOALS)))
418
+
419
+ifneq ($(strip $(BUILDGOALS)),)
420
+# This is an auto-incrementing build.  Forcibly rebuild .buildserial.h
421
+# and mark config.o as depending on it to force its rebuilding.
422
+bin/config.o : include/.buildserial.h
423
+.PHONY : include/.buildserial.h
424
+endif # BUILDGOALS
425
+
426
+include/.buildserial.h :
427
+	@if [ ! -f $@ ]; then 	echo '#define BUILD_SERIAL_NUM 0' > $@; fi
428
+	@perl -pi -e 's/(BUILD_SERIAL_NUM)\s+(\d+)/"$${1} ".($${2}+1)/e' $@
429
+
430
+buildserial : include/.buildserial.h
431
+	@perl -n -e '/BUILD_SERIAL_NUM\s+(\d+)/ && ' \
432
+		-e 'print "Build serial number is $$1\n";' $<
433
+
434
+else # -DBUILD_SERIAL
435
+
436
+buildserial : 
437
+	@echo Build serial number is disabled. Enable -DBUILD_SERIAL in Config.
438
+
439
+endif # -DBUILD_SERIAL
440
+
441
+bs : buildserial
442
+
443
+version:
444
+	@echo $(VERSION)
445
+
446
+romlimit:
447
+	@echo $(ROMLIMIT)
448
+
449
+sources:
450
+	@echo $(SRCS)

+ 90
- 0
src/README.pixify View File

@@ -0,0 +1,90 @@
1
+This file documents the driver changes needed to support use as part
2
+of a PXE stack.
3
+
4
+PROPER WAY
5
+==========
6
+
7
+1. The probe() routine.
8
+
9
+There are three additional fields that need to be filled in the nic
10
+structure: ioaddr, irqno and irq.
11
+
12
+  ioaddr is the base I/O address and seems to be for information only;
13
+  no use will be made of this value other than displaying it on the
14
+  screen.
15
+
16
+  irqno must be the IRQ number for the NIC.  For PCI NICs this can
17
+  simply be copied from pci->irq.
18
+
19
+  irq is a function pointer, like poll and transmit.  It must point to
20
+  the driver's irq() function.
21
+
22
+2. The poll() routine.
23
+
24
+This must take an additional parameter: "int retrieve".  Calling
25
+poll() with retrieve!=0 should function exactly as before.  Calling
26
+poll() with retrieve==0 indicates that poll() should check for the
27
+presence of a packet to read, but must *not* read the packet.  The
28
+packet will be read by a subsequent call to poll() with retrieve!=0.
29
+
30
+The easiest way to implement this is to insert the line
31
+  if ( ! retrieve ) return 1;
32
+between the "is there a packet ready" and the "fetch packet" parts of
33
+the existing poll() routine.
34
+
35
+Care must be taken that a call to poll() with retrieve==0 does not
36
+clear the NIC's "packet ready" status indicator, otherwise the
37
+subsequent call to poll() with retrieve!=0 will fail because it will
38
+think that there is no packet to read.
39
+
40
+poll() should also acknowledge and clear the NIC's "packet received"
41
+interrupt.  It does not need to worry about enabling/disabling
42
+interrupts; this is taken care of by calls to the driver's irq()
43
+routine.
44
+
45
+Etherboot will forcibly regenerate an interrupt if a packet remains
46
+pending after all interrupts have been acknowledged.  You can
47
+therefore get away with having poll() just acknolwedge and clear all
48
+NIC interrupts, without particularly worrying about exactly when this
49
+should be done.
50
+
51
+3. The irq() routine.
52
+
53
+This is a new routine, with prototype
54
+  void DRIVER_irq ( struct nic *nic, irq_action_t action );
55
+"action" takes one of three possible values: ENABLE, DISABLE or FORCE.
56
+ENABLE and DISABLE mean to enable/disable the NIC's "packet received"
57
+interrupt.  FORCE means that the NIC should be forced to generate a
58
+fake "packet received" interrupt.
59
+
60
+If you are unable to implement FORCE, your NIC will not work when
61
+being driven via the UNDI interface under heavy network traffic
62
+conditions.  Since Etherboot's UNDI driver (make bin/undi.zpxe) is the
63
+only program known to use this interface, it probably doesn't really
64
+matter.
65
+
66
+
67
+QUICK AND DIRTY WAY
68
+===================
69
+
70
+It is possible to use the system timer interrupt (IRQ 0) rather than a
71
+genuine NIC interrupt.  Since there is a constant stream of timer
72
+interrupts, the net upshot is a whole load of spurious "NIC"
73
+interrupts that have no effect other than to cause unnecessary PXE API
74
+calls.  It's inefficient but it works.
75
+
76
+To achieve this, simply set nic->irqno=0 in probe() and point nic->irq
77
+to a dummy routine that does nothing.  Add the line
78
+  if ( ! retrieve ) return 1;
79
+at the beginning of poll(), to prevent the packet being read (and
80
+discarded) when poll() is called with retrieve==0;
81
+
82
+
83
+UNCONVERTED DRIVERS
84
+===================
85
+
86
+Drivers that have not yet been converted should continue to function
87
+when not used as part of a PXE stack, although there will be a
88
+harmless compile-time warning about assignment from an incompatible
89
+pointer type in the probe() function, since the prototype for the
90
+poll() function is missing the "int retrieve" parameter.

+ 23
- 0
src/arch/armnommu/Config View File

@@ -0,0 +1,23 @@
1
+# Config for armnommu Etherboot
2
+#
3
+
4
+# For a clean compilation, switch in global Config
5
+# off: -DCONFIG_PCI, -DTAGGED_IMAGE, -DELF_IMAGE, -DPXE*, -DRELOCATE and INCLUDE_FILO
6
+# on : -DRAW_IMAGE
7
+
8
+# Serial line settings
9
+CFLAGS+= -DCONSOLE_SERIAL -DCONSPEED=57600
10
+
11
+# System Frequency
12
+CFLAGS+= -DSYSCLK=73728000
13
+
14
+# Image Download Address
15
+CFLAGS+= -DRAWADDR=0x40100000
16
+
17
+# NIC Debug Outputs
18
+#CFLAGS+= -DDEBUG_NIC
19
+
20
+# Fixed MAC address
21
+# p2001_eth has no flash and fixed mac address
22
+#CFLAGS+=	-DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
23
+CFLAGS+=	-DMAC_HW_ADDR_DRV="0x00,0x09,0x4F,0x00,0x00,0x02"

+ 58
- 0
src/arch/armnommu/Makefile View File

@@ -0,0 +1,58 @@
1
+ARCH_FORMAT=	armnommu
2
+
3
+ROMLIMIT=	20480
4
+CHECKSIZE=	{ read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\
5
+	{ $(RM) $@; echo "ERROR: code size exceeds limit!"; exit 1; }; exit 0; }
6
+
7
+START=	$(BIN)/start.o
8
+
9
+SRCS+=	arch/armnommu/core/arm_timer.c
10
+SRCS+=	arch/armnommu/core/start.S
11
+SRCS+=	arch/armnommu/core/serial.c
12
+SRCS+=	arch/armnommu/core/mem.c
13
+SRCS+=	arch/armnommu/core/setjmp.S
14
+SRCS+=	arch/armnommu/drivers/net/p2001_eth.c
15
+
16
+# not greater than 100kB
17
+ROMLIMIT:=1024000
18
+
19
+include		$(BIN)/Roms
20
+
21
+ROMS= $(BIN)/p2001_eth.rom
22
+IMGS= $(BIN)/p2001_eth.img
23
+
24
+
25
+allfiles:	$(ROMS)
26
+
27
+BOBJS+=		$(BIN)/arm_timer.o
28
+BOBJS+=		$(BIN)/serial.o
29
+BOBJS+=		$(BIN)/mem.o
30
+BOBJS+=		$(BIN)/setjmp.o
31
+BOBJS+=		$(BIN)/lib1funcs.o
32
+
33
+# Utilities
34
+
35
+$(BIN)/nrv2b:	util/nrv2b.c
36
+	$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
37
+
38
+# Pattern Rules
39
+# General for compiling/assembly source files
40
+$(BIN)/%.o:	arch/armnommu/core/%.c $(MAKEDEPS)
41
+	$(CC) $(CFLAGS) -o $@ -c $<
42
+
43
+$(BIN)/%.o:	arch/armnommu/drivers/net/%.c $(MAKEDEPS)
44
+	$(CC) $(CFLAGS) -o $@ -c $<
45
+
46
+$(BIN)/%.S:	arch/armnommu/core/%.c $(MAKEDEPS)
47
+	$(CC) $(CFLAGS) -S -o $@ -c $<
48
+
49
+$(BIN)/%.o:	arch/armnommu/core/%.S $(MAKEDEPS)
50
+	$(CPP) $(CFLAGS) -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
51
+
52
+# general ruls for generating .img files
53
+$(BIN)/%.tmp: $(BIN)/%.o $(START) $(BIN)/config.o arch/$(ARCH)/core/etherboot.lds $(LIBS) $(STDDEPS) $(MAKEDEPS)
54
+	$(LD) $(LDFLAGS) -T arch/$(ARCH)/core/etherboot.lds -o $@ $(START) $(BIN)/config.o $< $(LIBS)
55
+	@$(SIZE) $@ | $(CHECKSIZE)
56
+
57
+$(BIN)/%.img: $(BIN)/%.tmp $(MAKEDEPS)
58
+	$(OBJCOPY) -O binary $< $@

+ 77
- 0
src/arch/armnommu/core/arm_timer.c View File

@@ -0,0 +1,77 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#include "etherboot.h"
9
+#include "timer.h"
10
+#include "latch.h"
11
+#include "hardware.h"
12
+
13
+
14
+/* get timer returns the contents of the timer */
15
+static unsigned long get_timer(void)
16
+{
17
+	return P2001_TIMER->Freerun_Timer;
18
+}
19
+
20
+/* ------ Calibrate the TSC ------- 
21
+ * Time how long it takes to excute a loop that runs in known time.
22
+ * And find the convertion needed to get to CLOCK_TICK_RATE
23
+ */
24
+
25
+static unsigned long configure_timer(void)
26
+{
27
+	return (1);
28
+}
29
+
30
+static unsigned long clocks_per_tick = 1;
31
+
32
+void setup_timers(void)
33
+{
34
+	if (!clocks_per_tick) {
35
+		clocks_per_tick = configure_timer();
36
+	}
37
+}
38
+
39
+unsigned long currticks(void)
40
+{
41
+	return get_timer(); /* /clocks_per_tick */
42
+}
43
+
44
+static unsigned long timer_timeout;
45
+static int __timer_running(void)
46
+{
47
+	return get_timer() < timer_timeout;
48
+}
49
+
50
+void udelay(unsigned int usecs)
51
+{
52
+	unsigned long now;
53
+	now = get_timer();
54
+	timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
55
+	while(__timer_running());
56
+}
57
+void ndelay(unsigned int nsecs)
58
+{
59
+	unsigned long now;
60
+	now = get_timer();
61
+	timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
62
+	while(__timer_running());
63
+}
64
+
65
+void load_timer2(unsigned int timer2_ticks)
66
+{
67
+	unsigned long now;
68
+	unsigned long clocks;
69
+	now = get_timer();
70
+	clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
71
+	timer_timeout = now + clocks;
72
+}
73
+
74
+int timer2_running(void)
75
+{
76
+	return __timer_running();
77
+}

+ 55
- 0
src/arch/armnommu/core/etherboot.lds View File

@@ -0,0 +1,55 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
9
+OUTPUT_ARCH(arm)
10
+ENTRY(_start)
11
+SECTIONS
12
+{
13
+	/*. = 0x00000000;*/	/* PIC */
14
+	/*. = 0x00000400;*/	/* ROM Bootloader */
15
+	. = 0x40000000;		/* SDRAM */
16
+
17
+	. = ALIGN(4);
18
+	_text = . ;
19
+	.text      :
20
+	{
21
+	  _start = .;
22
+	  _virt_start = .;
23
+	  bin/start.o	(.text)
24
+	  *(.text)
25
+
26
+	  . = ALIGN(16);
27
+	  isa_drivers = . ;
28
+	  *(.drivers.isa);
29
+	  isa_drivers_end = . ;	  
30
+	}
31
+
32
+	. = ALIGN(4);
33
+	.rodata : { *(.rodata) }
34
+
35
+	. = ALIGN(4);
36
+	.data : { *(.data) }
37
+
38
+	. = ALIGN(4);
39
+	.got : { *(.got) }
40
+
41
+	. = ALIGN(4);
42
+	_bss = . ;
43
+	.bss : { *(.bss) }
44
+
45
+	. = ALIGN(4);
46
+	_ebss = .;
47
+	_end = .;
48
+
49
+	. = ALIGN(16);
50
+	.text :
51
+	{
52
+		*(.dma.desc);
53
+		*(.dma.buffer);
54
+	}
55
+}

+ 105
- 0
src/arch/armnommu/core/lib1funcs.c View File

@@ -0,0 +1,105 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+
9
+
10
+/*
11
+ * from gcc/config/udivmodsi4.c
12
+ */
13
+unsigned long
14
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
15
+{
16
+  unsigned long bit = 1;
17
+  unsigned long res = 0;
18
+
19
+  while (den < num && bit && !(den & (1L<<31)))
20
+    {
21
+      den <<=1;
22
+      bit <<=1;
23
+    }
24
+  while (bit)
25
+    {
26
+      if (num >= den)
27
+	{
28
+	  num -= den;
29
+	  res |= bit;
30
+	}
31
+      bit >>=1;
32
+      den >>=1;
33
+    }
34
+  if (modwanted) return num;
35
+  return res;
36
+}
37
+
38
+
39
+/*
40
+ * from gcc/config/udivmod.c
41
+ */
42
+long
43
+__udivsi3 (long a, long b)
44
+{
45
+  return udivmodsi4 (a, b, 0);
46
+}
47
+
48
+long
49
+__umodsi3 (long a, long b)
50
+{
51
+  return udivmodsi4 (a, b, 1);
52
+}
53
+
54
+
55
+/*
56
+ * from gcc/config/divmod.c
57
+ */
58
+long
59
+__divsi3 (long a, long b)
60
+{
61
+  int neg = 0;
62
+  long res;
63
+
64
+  if (a < 0)
65
+    {
66
+      a = -a;
67
+      neg = !neg;
68
+    }
69
+
70
+  if (b < 0)
71
+    {
72
+      b = -b;
73
+      neg = !neg;
74
+    }
75
+
76
+  res = udivmodsi4 (a, b, 0);
77
+
78
+  if (neg)
79
+    res = -res;
80
+
81
+  return res;
82
+}
83
+
84
+long
85
+__modsi3 (long a, long b)
86
+{
87
+  int neg = 0;
88
+  long res;
89
+
90
+  if (a < 0)
91
+    {
92
+      a = -a;
93
+      neg = 1;
94
+    }
95
+
96
+  if (b < 0)
97
+    b = -b;
98
+
99
+  res = udivmodsi4 (a, b, 1);
100
+
101
+  if (neg)
102
+    res = -res;
103
+
104
+  return res;
105
+}

+ 27
- 0
src/arch/armnommu/core/mem.c View File

@@ -0,0 +1,27 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#include "hooks.h"
9
+#include "io.h"
10
+#include "etherboot.h"
11
+
12
+struct meminfo meminfo;
13
+void get_memsizes(void)
14
+{
15
+/* We initialize the meminfo structure 
16
+ * according to our development board's specs
17
+ * We do not have a way to automatically probe the 
18
+ * memspace instead we initialize it manually
19
+ */
20
+	meminfo.basememsize = 0x00000000;
21
+	meminfo.memsize     = 0x00008000;
22
+	meminfo.map_count   = 1;
23
+
24
+	meminfo.map[0].addr = 0x40000000;
25
+	meminfo.map[0].size = 0x01000000;
26
+	meminfo.map[0].type = E820_RAM;
27
+}

+ 48
- 0
src/arch/armnommu/core/raw_loader.c View File

@@ -0,0 +1,48 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifdef RAW_IMAGE
9
+static unsigned long raw_load_addr;
10
+
11
+int mach_boot(register unsigned long entry_point)
12
+{
13
+	void (*fnc)(void) = (void *) entry_point;
14
+	// r0 = 0
15
+	// r1 = 625 (machine nr. MACH_TYPE_P2001)
16
+	(*fnc)();
17
+
18
+	return 0; /* We should never reach this point ! */
19
+}
20
+
21
+static sector_t raw_download(unsigned char *data, unsigned int len, int eof)
22
+{
23
+	memcpy(phys_to_virt(raw_load_addr), data, len);
24
+	raw_load_addr += len;
25
+	if (!eof)
26
+		return 0;
27
+
28
+	done(1);
29
+	printf("Starting program.\n");
30
+	mach_boot(RAWADDR);
31
+	printf("Bootsector returned?");
32
+	longjmp(restart_etherboot, -2);
33
+	return 1;
34
+}
35
+
36
+static os_download_t raw_probe(unsigned char *data __unused, unsigned int len __unused)
37
+{
38
+	printf("(RAW");
39
+	// probe something here...
40
+	printf(")... \n");
41
+
42
+	//raw_load_addr = phys_to_virt(_end);
43
+	raw_load_addr = RAWADDR;
44
+	printf("Writing image to 0x%x\n", raw_load_addr);
45
+	return raw_download;
46
+}
47
+
48
+#endif

+ 66
- 0
src/arch/armnommu/core/serial.c View File

@@ -0,0 +1,66 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#include "etherboot.h"
9
+#include "hardware.h"
10
+#ifdef	CONSOLE_SERIAL
11
+
12
+/*
13
+ * void serial_putc(int ch);
14
+ *	Write character `ch' to port UART_BASE.
15
+ */
16
+void serial_putc(int ch)
17
+{
18
+	/* wait for room in the 32 byte tx FIFO */
19
+	while ((P2001_UART->r.STATUS & 0x3f) > /* 30 */ 0) ;
20
+	P2001_UART->w.TX1 = ch & 0xff;
21
+}
22
+
23
+/*
24
+ * int serial_getc(void);
25
+ *	Read a character from port UART_BASE.
26
+ */
27
+int serial_getc(void)
28
+{
29
+	while (((P2001_UART->r.STATUS >> 6) & 0x3f) == 0) ;
30
+	return P2001_UART->r.RX1 & 0xff;
31
+}
32
+
33
+/*
34
+ * int serial_ischar(void);
35
+ *       If there is a character in the input buffer of port UART_BASE,
36
+ *       return nonzero; otherwise return 0.
37
+ */
38
+int serial_ischar(void)
39
+{
40
+	return (P2001_UART->r.STATUS >> 6) & 0x3f;
41
+}
42
+
43
+/*
44
+ * int serial_init(void);
45
+ *	Initialize port to speed 57.600, line settings 8N1.
46
+ */
47
+int serial_init(void)
48
+{
49
+	static unsigned int N;
50
+	// const M=3
51
+	P2001_UART->w.Clear = 0;		// clear
52
+	N = ((SYSCLK/8)*3)/CONSPEED;
53
+	P2001_UART->w.Baudrate = (N<<16)+3;	// set 57.600 BAUD
54
+	P2001_UART->w.Config = 0xcc100;		// set 8N1, *water = 12
55
+	return 1;
56
+}
57
+
58
+/*
59
+ * void serial_fini(void);
60
+ *	Cleanup our use of the serial port, in particular flush the
61
+ *	output buffer so we don't accidentially loose characters.
62
+ */
63
+void serial_fini(void)
64
+{
65
+}
66
+#endif

+ 33
- 0
src/arch/armnommu/core/setjmp.S View File

@@ -0,0 +1,33 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+.text
9
+
10
+.global sigsetjmp;
11
+.type sigsetjmp,%function
12
+.align 4;
13
+sigsetjmp:
14
+	/* Save registers */
15
+	stmia	r0, {v1-v6, sl, fp, sp, lr}
16
+
17
+	mov	r0, #0
18
+	bx	lr
19
+.size sigsetjmp,.-sigsetjmp;
20
+
21
+
22
+
23
+.global longjmp;
24
+.type longjmp,%function
25
+.align 4;
26
+longjmp:
27
+	mov	ip, r0		/* save jmp_buf pointer */
28
+
29
+	movs	r0, r1		/* get the return value in place */
30
+	moveq	r0, #1		/* can't let setjmp() return zero! */
31
+
32
+	ldmia	ip, {v1-v6, sl, fp, sp, pc}
33
+.size longjmp,.-longjmp;

+ 184
- 0
src/arch/armnommu/core/start.S View File

@@ -0,0 +1,184 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+.global _start
9
+
10
+/* Mode definitions */
11
+#define Mode_USR	0x10
12
+#define Mode_FIQ	0x11
13
+#define Mode_IRQ	0x12
14
+#define Mode_SVC	0x13
15
+#define Mode_ABT	0x17
16
+#define Mode_UNDEF	0x1B
17
+#define Mode_SYS	0x1F				// only available on ARM Arch. v4
18
+#define I_Bit		0x80
19
+#define F_Bit		0x40
20
+
21
+/* LPEC register definitions */
22
+#define Adr_SYS_BASE			0x00100000
23
+#define REL_Adr_SDRAM_Ctrl		0x10
24
+#define REL_Adr_ExtMem_Ctrl		0x14
25
+#define REL_Adr_WaitState_Ext		0x18
26
+#define REL_Adr_WaitState_Asic		0x1c
27
+#define Adr_TIMER_BASE			0x00110000
28
+#define REL_Adr_Timer12_PreDiv		0x0c
29
+#define REL_Adr_PLL_12000_config	0x30
30
+#define REL_Adr_PLL_12288_config	0x34
31
+#define REL_Adr_DIV_12288_config	0x38
32
+#define REL_Adr_FSC_CONFIG		0x44
33
+#define Adr_GPIO_BASE			0x00120000
34
+#define REL_Adr_NRES_OUT		0x2c
35
+
36
+
37
+
38
+/* Define entry point */
39
+.arm							// Next instruction will be ARM
40
+_start:
41
+
42
+/*
43
+ * Initialize memory system
44
+ */
45
+
46
+
47
+/*
48
+ * Initialize stack pointer registers
49
+ */
50
+
51
+/* Enter SVC mode and set up the SVC stack pointer */
52
+	mov	r0, #(Mode_SVC|I_Bit|F_Bit)
53
+	msr	cpsr_c, r0
54
+	ldr	sp, SP_SVC
55
+
56
+
57
+/*
58
+ * Initialize critical IO devices
59
+ */
60
+
61
+	/* watchdog off */
62
+	mov	r0, #Adr_TIMER_BASE
63
+	ldr	r1, Timer12_PreDiv
64
+	str	r1, [r0, #REL_Adr_Timer12_PreDiv]
65
+	
66
+	/* NRES=1 */
67
+	mov	r0, #Adr_GPIO_BASE
68
+	ldr	r1, NRES_OUT
69
+	str	r1, [r0, #REL_Adr_NRES_OUT]
70
+
71
+	/* ExtMem */
72
+	mov	r0, #Adr_SYS_BASE
73
+	ldr	r1, ExtMem_Ctrl
74
+	str	r1, [r0, #REL_Adr_ExtMem_Ctrl]
75
+
76
+	/* SDRAM */
77
+	mov	r0, #Adr_SYS_BASE
78
+	ldr	r1, SDRAM_Ctrl
79
+	str	r1, [r0, #REL_Adr_SDRAM_Ctrl]
80
+/*
81
+_wait_sdram_ctrl:
82
+	ldr	r1, [r0]
83
+	tst	r1, #0x20000
84
+	beq	_wait_sdram_ctrl
85
+*/
86
+
87
+	/* WaitState_Ext */
88
+	ldr	r1, WaitState_Ext
89
+	str	r1, [r0, #REL_Adr_WaitState_Ext]
90
+	/* WaitState_Asic */
91
+	ldr	r1, WaitState_Asic
92
+	str	r1, [r0, #REL_Adr_WaitState_Asic]
93
+
94
+	/* PLL_12288 */
95
+	mov	r0, #Adr_TIMER_BASE
96
+	ldr	r1, PLL_12288_config
97
+	str	r1, [r0, #REL_Adr_PLL_12288_config]
98
+	/* DIV_12288 */
99
+	ldr	r1, DIV_12288_config
100
+	str	r1, [r0, #REL_Adr_DIV_12288_config]
101
+	/* PLL_12200 */
102
+	ldr	r1, PLL_12000_config
103
+	str	r1, [r0, #REL_Adr_PLL_12000_config]
104
+
105
+	/* FSC_CONFIG */
106
+	ldr	r1, [r0, #REL_Adr_FSC_CONFIG]
107
+	bic	r1, r1, #0x07
108
+	ldr	r2, FSC_CONFIG
109
+	orr	r1, r1, r2
110
+	str	r1, [r0, #REL_Adr_FSC_CONFIG]
111
+
112
+
113
+/*
114
+ * Initialize interrupt system variables here
115
+ */
116
+
117
+
118
+/*
119
+ * Initialize memory required by main C code
120
+ */
121
+	
122
+
123
+/* jump to main program */
124
+	mov	r0, #0
125
+	b	main
126
+
127
+
128
+Timer12_PreDiv:
129
+	.word	0x40bb0000	/* watchdog off */
130
+NRES_OUT:
131
+	.word	0x00000003	/* NRES_OUT_DRV=1, NRES_OUT_DAT=1 */
132
+
133
+#if SYSCLK == 73728000
134
+ExtMem_Ctrl:
135
+	.word	0x000000e8	/* fuer FPGA 32 Bit konfiguriert */
136
+SDRAM_Ctrl:
137
+//	.word	0x28fc0037	/* default */
138
+	.word	0xaef40027	/* p2001_bit_compact */
139
+WaitState_Ext:
140
+	.word	0xa0001245	/* fuer 73 MHz */
141
+//	.word	0x0000fff3	/* rom bootloader */
142
+WaitState_Asic:
143
+	.word	0x00ff8a5f	/* fuer 85 MHz */
144
+//	.word	0x00000203	/* rom bootloader */
145
+PLL_12288_config:
146
+	.word	0x00000004	/* fuer 73 MHz */
147
+DIV_12288_config:
148
+	.word	0x00010601	/* fuer 73 MHz */
149
+PLL_12000_config:
150
+	.word	0x10004e75	/* fuer 85 MHz */
151
+FSC_CONFIG:
152
+	.word	0xc0000005	/* fuer 73 MHz */
153
+#else
154
+#error "Please define proper timings and wait states for that sysclk."
155
+#endif
156
+
157
+SP_SVC:
158
+	.word	0x40fffffc
159
+
160
+
161
+
162
+#ifndef	NORELOCATE
163
+/**************************************************************************
164
+RELOCATE_TO - relocate etherboot to the specified address
165
+**************************************************************************/
166
+	.global relocate_to
167
+
168
+relocate_to:
169
+	ldr	r1, =_start
170
+	ldr	r2, =_end
171
+
172
+	/* while (r1 < r2) { *(r0++) = *(r1++) } */
173
+_relocate_loop:
174
+	cmp	r1, r2
175
+	ldrcc	r3, [r1], #4
176
+	strcc	r3, [r0], #4
177
+	bcc	_relocate_loop
178
+	mov	pc, lr
179
+#endif
180
+
181
+
182
+.global __gccmain
183
+__gccmain:
184
+	mov	pc, lr		/* return from subroutine */

+ 525
- 0
src/arch/armnommu/drivers/net/p2001_eth.c View File

@@ -0,0 +1,525 @@
1
+/**************************************************************************
2
+Etherboot -  BOOTP/TFTP Bootstrap Program
3
+P2001 NIC driver for Etherboot
4
+***************************************************************************/
5
+
6
+/*
7
+ *  Copyright (C) 2004 Tobias Lorenz
8
+ *
9
+ * This program is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License version 2 as
11
+ * published by the Free Software Foundation.
12
+ */
13
+
14
+/* to get some global routines like printf */
15
+#include "etherboot.h"
16
+/* to get the interface to the body of the program */
17
+#include "nic.h"
18
+/* to get the ISA support functions, if this is an ISA NIC */
19
+#include "isa.h"
20
+
21
+#include "hardware.h"
22
+#include "lxt971a.h"
23
+#include "timer.h"
24
+
25
+
26
+/* NIC specific static variables go here */
27
+static unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
28
+
29
+/* DMA descriptors and buffers */
30
+#define NUM_RX_DESC     4	/* Number of Rx descriptor registers. */
31
+#define DMA_BUF_SIZE	2048	/* Buffer size */
32
+static DMA_DSC txd              __attribute__ ((__section__(".dma.desc")));
33
+static DMA_DSC rxd[NUM_RX_DESC] __attribute__ ((__section__(".dma.desc")));
34
+static unsigned char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
35
+static unsigned char txb[              DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
36
+static unsigned int cur_rx;
37
+
38
+/* Device selectors */
39
+static unsigned int cur_channel;	// DMA channel    : 0..3
40
+static unsigned int cur_phy;		// PHY Address    : 0..31
41
+static P2001_ETH_regs_ptr EU;		// Ethernet Unit  : 0x0018_000 with _=0..3
42
+static P2001_ETH_regs_ptr MU;		// Management Unit: 0x00180000
43
+
44
+#define MDIO_MAXCOUNT 1000			/* mdio abort */
45
+static unsigned int mdio_error;			/* mdio error */
46
+
47
+/* Function prototypes */
48
+static void         p2001_eth_mdio_init ();
49
+static void         p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data);
50
+static unsigned int p2001_eth_mdio_read (unsigned int phyadr, unsigned int regadr);
51
+extern unsigned int p2001_eth_mdio_error;
52
+
53
+static int          p2001_eth_poll      (struct nic *nic, int retrieve);
54
+static void         p2001_eth_transmit  (struct nic *nic, const char *d,
55
+					unsigned int t, unsigned int s, const char *p);
56
+
57
+static void         p2001_eth_irq       (struct nic *nic, irq_action_t action);
58
+
59
+static void         p2001_eth_init      ();
60
+static void         p2001_eth_disable   (struct dev *dev);
61
+
62
+static int          p2001_eth_check_link(unsigned int phy);
63
+static int          p2001_eth_probe     (struct dev *dev, unsigned short *probe_addrs __unused);
64
+
65
+
66
+/**************************************************************************
67
+PHY MANAGEMENT UNIT - Read/write
68
+***************************************************************************/
69
+static void p2001_eth_mdio_init()
70
+{
71
+	/* reset ethernet PHYs */
72
+	printf("Resetting PHYs...\n");
73
+
74
+	/* GPIO24/25: TX_ER2/TX_ER0 */
75
+	/* GPIO26/27: PHY_RESET/TX_ER1 */
76
+	P2001_GPIO->PIN_MUX |= 0x0018;
77
+	// 31-16: 0000 1111 0000 0000
78
+	P2001_GPIO->GPIO2_En |= 0x0400;
79
+
80
+	P2001_GPIO->GPIO2_Out |= 0x04000000;
81
+	P2001_GPIO->GPIO2_Out &= ~0x0400;
82
+	mdelay(500);
83
+	P2001_GPIO->GPIO2_Out |= 0x0400;
84
+
85
+	/* set management unit clock divisor */
86
+	// max. MDIO CLK = 2.048 MHz (EU.doc)
87
+	// max. MDIO CLK = 8.000 MHz (LXT971A)
88
+	// sysclk/(2*(n+1)) = MDIO CLK <= 2.048 MHz
89
+	// n >= sysclk/4.096 MHz - 1
90
+#if SYSCLK == 73728000
91
+	P2001_MU->MU_DIV = 17;	// 73.728 MHZ =17=> 2.020 MHz
92
+#else
93
+	//MU->MU_DIV = (SYSCLK/4.096)-1;
94
+#error "Please define a proper MDIO CLK divisor for that sysclk."
95
+#endif
96
+	asm("nop \n nop");
97
+}
98
+
99
+static void p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data)
100
+{
101
+	static unsigned int count;
102
+	count = 0;
103
+
104
+	/* Warten bis Hardware inaktiv (MIU = "0") */
105
+	while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
106
+		count++;
107
+
108
+	/* Schreiben MU_DATA */
109
+	MU->MU_DATA = data;
110
+
111
+	/* Schreiben MU_CNTL */
112
+	MU->MU_CNTL = regadr + (phyadr<<5) + (1<<10);
113
+
114
+	/* Warten bis Hardware aktiv (MIU = "1") */
115
+	while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
116
+		count++;
117
+	//asm("nop \r\n nop");
118
+
119
+	/* Warten bis Hardware inaktiv (MIU = "0") */
120
+	while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
121
+		count++;
122
+
123
+	mdio_error = (count >= MDIO_MAXCOUNT);
124
+}
125
+
126
+static unsigned int p2001_eth_mdio_read(unsigned int phyadr, unsigned int regadr)
127
+{
128
+	static unsigned int count;
129
+	count = 0;
130
+
131
+	do {
132
+		/* Warten bis Hardware inaktiv (MIU = "0") */
133
+		while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
134
+			count++;
135
+
136
+		/* Schreiben MU_CNTL */
137
+		MU->MU_CNTL = regadr + (phyadr<<5) + (2<<10);
138
+
139
+		/* Warten bis Hardware aktiv (MIU = "1") */
140
+		while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
141
+			count++;
142
+		//asm("nop \r\n nop");
143
+
144
+		/* Warten bis Hardware inaktiv (MIU = "0") */
145
+		while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
146
+			count++;
147
+
148
+		/* Fehler, wenn MDIO Read Error (MRE = "1") */
149
+	} while ((MU->MU_CNTL & 0x4000) && (count < MDIO_MAXCOUNT));
150
+
151
+	/* Lesen MU_DATA */
152
+	mdio_error = (count >= MDIO_MAXCOUNT);
153
+	return MU->MU_DATA;
154
+}
155
+
156
+
157
+/**************************************************************************
158
+POLL - Wait for a frame
159
+***************************************************************************/
160
+/* Function: p2001_eth_poll
161
+ *
162
+ * Description: checks for a received packet and returns it if found.
163
+ *
164
+ * Arguments: struct nic *nic:          NIC data structure
165
+ *
166
+ * Returns:   1 if a packet was received.
167
+ *            0 if no pacet was received.
168
+ *
169
+ * Side effects:
170
+ *            Returns (copies) the packet to the array nic->packet.
171
+ *            Returns the length of the packet in nic->packetlen.
172
+ */
173
+static int p2001_eth_poll(struct nic *nic, int retrieve)
174
+{
175
+	/* return true if there's an ethernet packet ready to read */
176
+	/* nic->packet should contain data on return */
177
+	/* nic->packetlen should contain length of data */
178
+
179
+	int retstat = 0;
180
+
181
+	if (rxd[cur_rx].stat & (1<<31))	// OWN
182
+		return retstat;
183
+
184
+	if (!retrieve)
185
+		return 1;
186
+
187
+	nic->packetlen = rxd[cur_rx].cntl & 0xffff;
188
+
189
+	if (rxd[cur_rx].stat & ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22))) {
190
+		/* corrupted packet received */
191
+		printf("p2001_eth_poll: Corrupted packet received, stat = %X\n",
192
+		               rxd[cur_rx].stat);
193
+		retstat = 0;
194
+	} else {
195
+		/* give packet to higher routine */
196
+		memcpy(nic->packet, (rxb + cur_rx*DMA_BUF_SIZE), nic->packetlen);
197
+		retstat = 1;
198
+	}
199
+
200
+#ifdef DEBUG_NIC
201
+	printf("p2001_eth_poll: packet from %! to %! received\n", 
202
+		(rxb+cur_rx*DMA_BUF_SIZE)+ETH_ALEN,
203
+		(rxb+cur_rx*DMA_BUF_SIZE));
204
+#endif
205
+
206
+	/* disable receiver */
207
+	// FIXME: is that ok? it can produce grave errors.
208
+	EU->RMAC_DMA_EN = 0;				/* clear run bit */
209
+
210
+	/* return the descriptor and buffer to receive ring */
211
+	rxd[cur_rx].stat = (1<<31) | (1<<30) | (1<<29);	// DSC0 OWN|START|END
212
+	rxd[cur_rx].cntl = (1<<23);			// DSC1 RECEIVE
213
+	rxd[cur_rx].cntl |= cur_channel << 16;		// DSC1 CHANNEL
214
+	rxd[cur_rx].cntl |= DMA_BUF_SIZE;		// DSC1 LEN
215
+
216
+	if (++cur_rx == NUM_RX_DESC)
217
+        	cur_rx = 0;
218
+
219
+	/* enable receiver */
220
+	if (!(EU->RMAC_DMA_EN & 0x01))
221
+		EU->RMAC_DMA_EN = 0x01;			/* set run bit */
222
+
223
+#ifdef DEBUG_NIC
224
+	printf("RMAC_MIB0..5: %d:%d:%d:%d:%d:%d\n",
225
+		EU->RMAC_MIB0, EU->RMAC_MIB1,
226
+		EU->RMAC_MIB2, EU->RMAC_MIB3,
227
+		EU->RMAC_MIB4, EU->RMAC_MIB5);
228
+#endif
229
+
230
+	return retstat;	/* initially as this is called to flush the input */
231
+}
232
+
233
+
234
+/**************************************************************************
235
+TRANSMIT - Transmit a frame
236
+***************************************************************************/
237
+/* Function: p2001_eth_transmit
238
+ *
239
+ * Description: transmits a packet and waits for completion or timeout.
240
+ *
241
+ * Arguments: char d[6]:          destination ethernet address.
242
+ *            unsigned short t:   ethernet protocol type.
243
+ *            unsigned short s:   size of the data-part of the packet.
244
+ *            char *p:            the data for the packet.
245
+ *    
246
+ * Returns:   void.
247
+ */
248
+static void p2001_eth_transmit(
249
+	struct nic *nic __unused,
250
+	const char *d,			/* Destination */
251
+	unsigned int t,			/* Type */
252
+	unsigned int s,			/* size */
253
+	const char *p)			/* Packet */
254
+{
255
+	unsigned int nstype;
256
+#ifdef DEBUG_NIC
257
+	unsigned int status;
258
+#endif
259
+
260
+	/* assemble packet */
261
+	memcpy(txb, d, ETH_ALEN);			// destination
262
+	memcpy(txb+ETH_ALEN, nic->node_addr, ETH_ALEN);	// source
263
+	nstype = htons(t);
264
+	memcpy(txb+2*ETH_ALEN, (char*)&nstype, 2);	// type
265
+	memcpy(txb+ETH_HLEN, p, s);			// packet
266
+	s += ETH_HLEN;
267
+
268
+	/* pad to minimum packet size */
269
+//	while (s<ETH_ZLEN)
270
+//		txb[s++] = '\0';
271
+	// TMAC_CNTL.ATP does the same
272
+
273
+#ifdef DEBUG_NIC
274
+	printf("p2001_eth_transmit: packet from %! to %! sent\n", txb+ETH_ALEN, txb);
275
+#endif
276
+
277
+	/* configure descriptor */
278
+	txd.stat = (1<<31) | (1<<30) | (1<<29);	// DSC0 OWN|START|END
279
+	txd.cntl = cur_channel << 16;		// DSC1 CHANNEL
280
+	txd.cntl |= s;				// DSC1 LEN
281
+
282
+	/* restart the transmitter */
283
+	EU->TMAC_DMA_EN = 0x01;		/* set run bit */
284
+	while(EU->TMAC_DMA_EN & 0x01) ;	/* wait */
285
+
286
+#ifdef DEBUG_NIC
287
+	/* check status */
288
+	status = EU->TMAC_DMA_STAT;
289
+	if (status & ~(0x40))
290
+		printf("p2001_eth_transmit: dma status=0x%hx\n", status);
291
+
292
+	printf("TMAC_MIB6..7: %d:%d\n", EU->TMAC_MIB6, EU->TMAC_MIB7);
293
+#endif
294
+}
295
+
296
+
297
+/**************************************************************************
298
+IRQ - Enable, Disable or Force Interrupts
299
+***************************************************************************/
300
+/* Function: p2001_eth_irq
301
+ *
302
+ * Description: Enable, Disable, or Force, interrupts
303
+ *    
304
+ * Arguments: struct nic *nic:          NIC data structure
305
+ *            irq_action_t action:      Requested action       
306
+ *
307
+ * Returns:   void.
308
+ */
309
+
310
+static void
311
+p2001_eth_irq(struct nic *nic __unused, irq_action_t action __unused)
312
+{
313
+	switch ( action ) {
314
+		case DISABLE :
315
+			break;
316
+		case ENABLE :
317
+			break;
318
+		case FORCE :
319
+			break;
320
+	}
321
+}
322
+
323
+
324
+/**************************************************************************
325
+INIT - Initialize device
326
+***************************************************************************/
327
+/* Function: p2001_init
328
+ *
329
+ * Description: resets the ethernet controller chip and various
330
+ *    data structures required for sending and receiving packets.
331
+ *    
332
+ * returns:   void.
333
+ */
334
+static void p2001_eth_init()
335
+{
336
+	static int i;
337
+
338
+	/* disable transceiver */
339
+//	EU->TMAC_DMA_EN = 0;		/* clear run bit */
340
+//	EU->RMAC_DMA_EN = 0;		/* clear run bit */
341
+
342
+	/* set rx filter (physical mac addresses) */
343
+	EU->RMAC_PHYU =
344
+		(MAC_HW_ADDR[0]<< 8) +
345
+		(MAC_HW_ADDR[1]<< 0);
346
+	EU->RMAC_PHYL =
347
+		(MAC_HW_ADDR[2]<<24) +
348
+		(MAC_HW_ADDR[3]<<16) +
349
+		(MAC_HW_ADDR[4]<<8 ) +
350
+		(MAC_HW_ADDR[5]<<0 );
351
+
352
+	/* initialize the tx descriptor ring */
353
+//	txd.stat = (1<<31) | (1<<30) | (1<<29);			// DSC0 OWN|START|END
354
+//	txd.cntl = cur_channel << 16;				// DSC1 CHANNEL
355
+//	txd.cntl |= DMA_BUF_SIZE;				// DSC1 LEN
356
+	txd.buf = &txb;						// DSC2 BUFFER
357
+	txd.next = &txd;					// DSC3 NEXTDSC @self
358
+	EU->TMAC_DMA_DESC = &txd;
359
+
360
+	/* initialize the rx descriptor ring */
361
+	cur_rx = 0;
362
+	for (i = 0; i < NUM_RX_DESC; i++) {
363
+		rxd[i].stat = (1<<31) | (1<<30) | (1<<29);	// DSC0 OWN|START|END
364
+		rxd[i].cntl = (1<<23);				// DSC1 RECEIVE
365
+		rxd[i].cntl |= cur_channel << 16;		// DSC1 CHANNEL
366
+		rxd[i].cntl |= DMA_BUF_SIZE;			// DSC1 LEN
367
+		rxd[i].buf = &rxb[i*DMA_BUF_SIZE];		// DSC2 BUFFER (EU-RX data)
368
+		rxd[i].next = &rxd[i+1];			// DSC3 NEXTDSC @next
369
+	}
370
+	rxd[NUM_RX_DESC-1].next = &rxd[0];			// DSC3 NEXTDSC @first
371
+	EU->RMAC_DMA_DESC = &rxd[0];
372
+
373
+	/* set transmitter mode */
374
+	EU->TMAC_CNTL = (1<<4) |	/* COI: Collision ignore */
375
+			//(1<<3) |	/* CSI: Carrier Sense ignore */
376
+			(1<<2);		/* ATP: Automatic Transmit Padding */
377
+
378
+	/* set receive mode */
379
+	EU->RMAC_CNTL = (1<<3) |	/* BROAD: Broadcast packets */
380
+			(1<<1);		/* PHY  : Packets to out MAC address */
381
+
382
+	/* enable receiver */
383
+	EU->RMAC_DMA_EN = 1;		/* set run bit */
384
+}
385
+
386
+
387
+/**************************************************************************
388
+DISABLE - Turn off ethernet interface
389
+***************************************************************************/
390
+static void p2001_eth_disable(struct dev *dev __unused)
391
+{
392
+	/* put the card in its initial state */
393
+	/* This function serves 3 purposes.
394
+	 * This disables DMA and interrupts so we don't receive
395
+	 *  unexpected packets or interrupts from the card after
396
+	 *  etherboot has finished. 
397
+	 * This frees resources so etherboot may use
398
+	 *  this driver on another interface
399
+	 * This allows etherboot to reinitialize the interface
400
+	 *  if something is something goes wrong.
401
+	 */
402
+
403
+	/* disable transmitter */
404
+	EU->TMAC_DMA_EN = 0;		/* clear run bit */
405
+
406
+	/* disable receiver */
407
+	EU->RMAC_DMA_EN = 0;		/* clear run bit */
408
+}
409
+
410
+
411
+/**************************************************************************
412
+LINK - Check for valid link
413
+***************************************************************************/
414
+static int p2001_eth_check_link(unsigned int phy)
415
+{
416
+	static int status;
417
+	static unsigned int count;
418
+	count = 0;
419
+
420
+	/* Use 0x3300 for restarting NWay */
421
+	printf("Starting auto-negotiation... ");
422
+	p2001_eth_mdio_write(phy, Adr_LXT971A_Control, 0x3300);
423
+	if (mdio_error)
424
+		goto failed;
425
+
426
+	/* Bits 1.5 and 17.7 are set to 1 once the Auto-Negotiation process to completed. */
427
+	do {
428
+		mdelay(500);
429
+		status = p2001_eth_mdio_read(phy, Adr_LXT971A_Status1);
430
+		if (mdio_error || (count++ > 6))	// 6*500ms = 3s timeout
431
+			goto failed;
432
+	} while (!(status & 0x20));
433
+	
434
+	/* Bits 1.2 and 17.10 are set to 1 once the link is established. */
435
+	if (p2001_eth_mdio_read(phy, Adr_LXT971A_Status1) & 0x04) {
436
+		/* Bits 17.14 and 17.9 can be used to determine the link operation conditions (speed and duplex). */
437
+		printf("Valid link, operating at: %sMb-%s\n",
438
+			(p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x4000) ? "100" : "10",
439
+			(p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x0200) ? "FD" : "HD");
440
+			return 1;
441
+	}
442
+
443
+failed:
444
+	if (mdio_error)
445
+		printf("Failed\n");
446
+	else
447
+		printf("No valid link\n");
448
+	return 0;
449
+}
450
+
451
+
452
+/**************************************************************************
453
+PROBE - Look for an adapter, this routine's visible to the outside
454
+***************************************************************************/
455
+static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused)
456
+{
457
+	struct nic *nic = (struct nic *)dev;
458
+	/* if probe_addrs is 0, then routine can use a hardwired default */
459
+	static int board_found;
460
+	static int valid_link;
461
+
462
+	/* reset phys and configure mdio clk */
463
+	p2001_eth_mdio_init();
464
+
465
+	/* find the correct PHY/DMA/MAC combination */
466
+	MU = P2001_MU;	// MU for all PHYs is only in EU0
467
+	printf("Searching for P2001 NICs...\n");
468
+	for (cur_channel=0; cur_channel<4; cur_channel++) {
469
+		switch(cur_channel) {
470
+			case 0:
471
+				EU = P2001_EU0;
472
+				cur_phy = 0;
473
+				break;
474
+			case 1:
475
+				EU = P2001_EU1;
476
+				cur_phy = 1;
477
+				break;
478
+			case 2:
479
+				EU = P2001_EU2;
480
+				cur_phy = 2;
481
+				break;
482
+			case 3:
483
+				EU = P2001_EU3;
484
+				cur_phy = 3;
485
+				break;
486
+		}
487
+
488
+		/* first a non destructive test for initial value RMAC_TLEN=1518 */
489
+		board_found = (EU->RMAC_TLEN == 1518);
490
+		if (board_found) {
491
+			printf("Checking EU%d...\n", cur_channel);
492
+
493
+			valid_link = p2001_eth_check_link(cur_phy);
494
+			if (valid_link) {
495
+				/* initialize device */
496
+				p2001_eth_init(nic);
497
+
498
+				/* set node address */
499
+				printf("Setting MAC address to %!\n", MAC_HW_ADDR);
500
+				memcpy(nic->node_addr, MAC_HW_ADDR, 6);
501
+
502
+				/* point to NIC specific routines */
503
+				dev->disable  = p2001_eth_disable;
504
+				nic->poll     = p2001_eth_poll;
505
+				nic->transmit = p2001_eth_transmit;
506
+				nic->irq      = p2001_eth_irq;
507
+
508
+				/* Report the ISA pnp id of the board */
509
+				dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
510
+				dev->devid.vendor_id = htons(0x1234);
511
+				return 1;
512
+			}
513
+		}
514
+	}
515
+	/* else */
516
+	return 0;
517
+}
518
+
519
+ISA_ROM("p2001_eth", "P2001 Ethernet Driver")
520
+static struct isa_driver p2001_eth_driver __isa_driver = {
521
+	.type    = NIC_DRIVER,
522
+	.name    = "P2001 Ethernet Driver",
523
+	.probe   = p2001_eth_probe,
524
+	.ioaddrs = 0,
525
+};

+ 47
- 0
src/arch/armnommu/include/bits/byteswap.h View File

@@ -0,0 +1,47 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ETHERBOOT_BITS_BYTESWAP_H
9
+#define ETHERBOOT_BITS_BYTESWAP_H
10
+
11
+/* We do not have byte swap functions ... We are
12
+ * RISC processor ...
13
+ */
14
+
15
+static inline unsigned short __swap16(volatile unsigned short v)
16
+{
17
+    return ((v << 8) | (v >> 8));
18
+}
19
+
20
+static inline unsigned int __swap32(volatile unsigned long v)
21
+{
22
+    return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
23
+}
24
+
25
+#define __bswap_constant_16(x) \
26
+	((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
27
+		(((uint16_t)(x) & 0xff00) >> 8)))
28
+
29
+#define __bswap_constant_32(x) \
30
+	((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
31
+		(((uint32_t)(x) & 0x0000ff00U) <<  8) | \
32
+		(((uint32_t)(x) & 0x00ff0000U) >>  8) | \
33
+		(((uint32_t)(x) & 0xff000000U) >> 24)))
34
+
35
+# define __bswap_16(x) \
36
+    (__extension__							      \
37
+     ({ unsigned short int __bsx = (x);					      \
38
+        ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))
39
+
40
+
41
+# define __bswap_32(x) \
42
+    (__extension__							      \
43
+     ({ unsigned int __bsx = (x);					      \
44
+        ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >>  8) |    \
45
+	 (((__bsx) & 0x0000ff00) <<  8) | (((__bsx) & 0x000000ff) << 24)); }))
46
+
47
+#endif /* ETHERBOOT_BITS_BYTESWAP_H */

+ 13
- 0
src/arch/armnommu/include/bits/cpu.h View File

@@ -0,0 +1,13 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ARM_BITS_CPU_H
9
+#define ARM_BITS_CPU_H
10
+
11
+#define cpu_setup() do {} while(0)
12
+
13
+#endif /* ARM_BITS_CPU_H */

+ 18
- 0
src/arch/armnommu/include/bits/elf.h View File

@@ -0,0 +1,18 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ARM_BITS_ELF_H
9
+#define ARM_BITS_ELF_H
10
+
11
+/* ELF Defines for the current architecture */
12
+#define	EM_CURRENT	EM_ARM
13
+#define ELFDATA_CURRENT	ELFDATA2LSB
14
+
15
+#define ELF_CHECK_ARCH(x) \
16
+	((x).e_machine == EM_CURRENT)
17
+
18
+#endif /* ARM_BITS_ELF_H */

+ 17
- 0
src/arch/armnommu/include/bits/endian.h View File

@@ -0,0 +1,17 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ETHERBOOT_BITS_ENDIAN_H
9
+#define ETHERBOOT_BITS_ENDIAN_H
10
+
11
+#ifdef __ARMEB__
12
+#define __BYTE_ORDER __BIG_ENDIAN
13
+#else
14
+#define __BYTE_ORDER __LITTLE_ENDIAN
15
+#endif
16
+
17
+#endif /* ETHERBOOT_BITS_ENDIAN_H */

+ 11
- 0
src/arch/armnommu/include/bits/string.h View File

@@ -0,0 +1,11 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ETHERBOOT_BITS_STRING_H
9
+#define ETHERBOOT_BITS_STRING_H
10
+
11
+#endif /* ETHERBOOT_BITS_STRING_H */

+ 1
- 0
src/arch/armnommu/include/callbacks_arch.h View File

@@ -0,0 +1 @@
1
+/* empty file */

+ 179
- 0
src/arch/armnommu/include/hardware.h View File

@@ -0,0 +1,179 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+
9
+/*
10
+ * Architecture: ARM9TDMI
11
+ * Processor   : P2001
12
+ */
13
+
14
+#ifndef ARCH_HARDWARE_H
15
+#define ARCH_HARDWARE_H
16
+
17
+#ifndef __ASSEMBLY__
18
+
19
+/* DMA descriptor */
20
+typedef struct {
21
+	unsigned int stat;			/* status: own, start, end, offset, status */
22
+	unsigned int cntl;			/* control: loop, int, type, channel, length */
23
+	char	*buf;				/* buffer */
24
+	void	*next;				/* nextdsc */
25
+} DMA_DSC;
26
+
27
+
28
+/* The address definitions are from asic_bf.h */
29
+typedef struct {					// 0x00100000U
30
+	volatile unsigned int reserved1[0x3];
31
+	volatile unsigned int ArmDmaPri;		// 0x0000000CU
32
+	volatile unsigned int SDRAM_Ctrl;		// 0x00000010U
33
+	volatile unsigned int ExtMem_Ctrl;		// 0x00000014U
34
+	volatile unsigned int WaitState_Ext;		// 0x00000018U
35
+	volatile unsigned int WaitState_Asic;		// 0x0000001CU
36
+	volatile unsigned int TOP;			// 0x00000020U
37
+	volatile unsigned int reserved2[0x3];
38
+	volatile unsigned int Adr1_EQ_30Bit;		// 0x00000030U
39
+	volatile unsigned int Adr2_EQ_30Bit;		// 0x00000034U
40
+	volatile unsigned int Adr3_EQ_30Bit;		// 0x00000038U
41
+	volatile unsigned int Dat3_EQ_32Bit;		// 0x0000003CU
42
+	volatile unsigned int Adr4_HE_20Bit;		// 0x00000040U
43
+	volatile unsigned int Adr4_LT_20Bit;		// 0x00000044U
44
+	volatile unsigned int Adr5_HE_20Bit;		// 0x00000048U
45
+	volatile unsigned int Adr5_LT_20Bit;		// 0x0000004CU
46
+	volatile unsigned int Adr_Control;		// 0x00000050U
47
+	volatile unsigned int ABORT_IA_32Bit;		// 0x00000054U
48
+} *P2001_SYS_regs_ptr;
49
+#define P2001_SYS ((volatile P2001_SYS_regs_ptr) 0x00100000)
50
+
51
+typedef struct {					// 0x00110000U
52
+	volatile unsigned int Timer1;			// 0x00000000U
53
+	volatile unsigned int Timer2;			// 0x00000004U
54
+	volatile unsigned int TIMER_PRELOAD;		// 0x00000008U
55
+	volatile unsigned int Timer12_PreDiv;		// 0x0000000CU
56
+	volatile unsigned int TIMER_INT;		// 0x00000010U
57
+	volatile unsigned int Freerun_Timer;		// 0x00000014U
58
+	volatile unsigned int WatchDog_Timer;		// 0x00000018U
59
+	volatile unsigned int PWM_CNT;			// 0x00000020U
60
+	volatile unsigned int PWM_CNT2;			// 0x00000024U
61
+	volatile unsigned int PLL_12000_config;		// 0x00000030U
62
+	volatile unsigned int PLL_12288_config;		// 0x00000034U
63
+	volatile unsigned int DIV_12288_config;		// 0x00000038U
64
+	volatile unsigned int MOD_CNT_768;		// 0x0000003CU
65
+	volatile unsigned int FSC_IRQ_STATUS;		// 0x00000040U
66
+	volatile unsigned int FSC_CONFIG;		// 0x00000044U
67
+	volatile unsigned int FSC_CONSTRUCT;		// 0x00000048U
68
+	volatile unsigned int FSC_base_clk_reg;		// 0x0000004CU
69
+	volatile unsigned int SYSCLK_SHAPE;		// 0x00000050U
70
+	volatile unsigned int SDRAMCLK_SHAPE;		// 0x00000054U
71
+	volatile unsigned int RING_OSZI;		// 0x00000058U
72
+} *P2001_TIMER_regs_ptr;
73
+#define P2001_TIMER ((volatile P2001_TIMER_regs_ptr) 0x00110000)
74
+
75
+typedef struct {					// 0x00120000U
76
+	volatile unsigned int reserved1[0x5];
77
+	volatile unsigned int GPIO_Config;		// 0x00000014U
78
+	volatile unsigned int GPIO_INT;			// 0x00000018U
79
+	volatile unsigned int GPIO_Out;			// 0x0000001CU
80
+	volatile unsigned int GPIO_IN;			// 0x00000020U
81
+	volatile unsigned int GPIO_En;			// 0x00000024U
82
+	volatile unsigned int PIN_MUX;			// 0x00000028U
83
+	volatile unsigned int NRES_OUT;			// 0x0000002CU
84
+	volatile unsigned int GPIO2_Out;		// 0x00000030U
85
+	volatile unsigned int GPIO2_IN;			// 0x00000034U
86
+	volatile unsigned int GPIO2_En;			// 0x00000038U
87
+	volatile unsigned int GPIO_INT_SEL;		// 0x0000003CU
88
+	volatile unsigned int GPI3_IN;			// 0x00000040U
89
+	volatile unsigned int GPO4_OUT;			// 0x00000044U
90
+} *P2001_GPIO_regs_ptr;
91
+#define P2001_GPIO ((volatile P2001_GPIO_regs_ptr) 0x00120000)
92
+
93
+typedef struct {					// 0x00130000U
94
+	volatile unsigned int Main_NFIQ_Int_Ctrl;	// 0x00000000U
95
+	volatile unsigned int Main_NIRQ_Int_Ctrl;	// 0x00000004U
96
+	volatile unsigned int Status_NFIQ;		// 0x00000008U
97
+	volatile unsigned int Status_NIRQ;		// 0x0000000CU
98
+} *P2001_INT_CTRL_regs_ptr;
99
+#define P2001_INT_CTRL ((volatile P2001_INT_CTRL_regs_ptr) 0x00130000)
100
+
101
+typedef union {						// 0x00140000U
102
+	struct {	// write
103
+		volatile unsigned int TX1;		// 0x00000000U
104
+		volatile unsigned int TX2;		// 0x00000004U
105
+		volatile unsigned int TX3;		// 0x00000008U
106
+		volatile unsigned int TX4;		// 0x0000000CU
107
+		volatile unsigned int Baudrate;		// 0x00000010U
108
+		volatile unsigned int reserved1[0x3];
109
+		volatile unsigned int Config;		// 0x00000020U
110
+		volatile unsigned int Clear;		// 0x00000024U
111
+		volatile unsigned int Echo_EN;		// 0x00000028U
112
+		volatile unsigned int IRQ_Status;	// 0x0000002CU
113
+	} w;		// write
114
+	
115
+	struct {	// read
116
+		volatile unsigned int RX1;		// 0x00000000U
117
+		volatile unsigned int RX2;		// 0x00000004U
118
+		volatile unsigned int RX3;		// 0x00000008U
119
+		volatile unsigned int RX4;		// 0x0000000CU
120
+		volatile unsigned int reserved1[0x4];
121
+		volatile unsigned int PRE_STATUS;	// 0x00000020U
122
+		volatile unsigned int STATUS;		// 0x00000024U
123
+		volatile unsigned int reserved2[0x1];
124
+		volatile unsigned int IRQ_Status;	// 0x0000002CU
125
+	} r;		// read
126
+} *P2001_UART_regs_ptr;
127
+#define P2001_UART ((volatile P2001_UART_regs_ptr) 0x00140000)
128
+
129
+typedef struct {				// 0x0018_000U _=0,1,2,3
130
+	volatile DMA_DSC *    RMAC_DMA_DESC;	// 0x00000000U
131
+	volatile unsigned int RMAC_DMA_CNTL;	// 0x00000004U
132
+	volatile unsigned int RMAC_DMA_STAT;	// 0x00000008U
133
+	volatile unsigned int RMAC_DMA_EN;	// 0x0000000CU
134
+	volatile unsigned int RMAC_CNTL;	// 0x00000010U
135
+	volatile unsigned int RMAC_TLEN;	// 0x00000014U
136
+	volatile unsigned int RMAC_PHYU;	// 0x00000018U
137
+	volatile unsigned int RMAC_PHYL;	// 0x0000001CU
138
+	volatile unsigned int RMAC_PFM0;	// 0x00000020U
139
+	volatile unsigned int RMAC_PFM1;	// 0x00000024U
140
+	volatile unsigned int RMAC_PFM2;	// 0x00000028U
141
+	volatile unsigned int RMAC_PFM3;	// 0x0000002CU
142
+	volatile unsigned int RMAC_PFM4;	// 0x00000030U
143
+	volatile unsigned int RMAC_PFM5;	// 0x00000034U
144
+	volatile unsigned int RMAC_PFM6;	// 0x00000038U
145
+	volatile unsigned int RMAC_PFM7;	// 0x0000003CU
146
+	volatile unsigned int RMAC_MIB0;	// 0x00000040U
147
+	volatile unsigned int RMAC_MIB1;	// 0x00000044U
148
+	volatile unsigned int RMAC_MIB2;	// 0x00000048U
149
+	volatile unsigned int RMAC_MIB3;	// 0x0000004CU
150
+	volatile unsigned int RMAC_MIB4;	// 0x00000050U
151
+	volatile unsigned int RMAC_MIB5;	// 0x00000054U
152
+	volatile unsigned int reserved1[0x1e8];
153
+	volatile unsigned int RMAC_DMA_DATA;	// 0x000007F8U
154
+	volatile unsigned int RMAC_DMA_ADR;	// 0x000007FCU
155
+	volatile DMA_DSC *    TMAC_DMA_DESC;	// 0x00000800U
156
+	volatile unsigned int TMAC_DMA_CNTL;	// 0x00000804U
157
+	volatile unsigned int TMAC_DMA_STAT;	// 0x00000808U
158
+	volatile unsigned int TMAC_DMA_EN;	// 0x0000080CU
159
+	volatile unsigned int TMAC_CNTL;	// 0x00000810U
160
+	volatile unsigned int TMAC_MIB6;	// 0x00000814U
161
+	volatile unsigned int TMAC_MIB7;	// 0x00000818U
162
+	volatile unsigned int reserved2[0x1];
163
+	volatile unsigned int MU_CNTL;		// 0x00000820U
164
+	volatile unsigned int MU_DATA;		// 0x00000824U
165
+	volatile unsigned int MU_DIV;		// 0x00000828U
166
+	volatile unsigned int CONF_RMII;	// 0x0000082CU
167
+	volatile unsigned int reserved3[0x1f2];
168
+	volatile unsigned int TMAC_DMA_DATA;	// 0x00000FF8U
169
+	volatile unsigned int TMAC_DMA_ADR;	// 0x00000FFCU
170
+} *P2001_ETH_regs_ptr;
171
+#define P2001_EU0 ((volatile P2001_ETH_regs_ptr) 0x00180000)
172
+#define P2001_EU1 ((volatile P2001_ETH_regs_ptr) 0x00181000)
173
+#define P2001_EU2 ((volatile P2001_ETH_regs_ptr) 0x00182000)
174
+#define P2001_EU3 ((volatile P2001_ETH_regs_ptr) 0x00183000)
175
+#define P2001_MU  P2001_EU0
176
+
177
+#endif
178
+
179
+#endif  /* ARCH_HARDWARE_H */

+ 25
- 0
src/arch/armnommu/include/hooks.h View File

@@ -0,0 +1,25 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ETHERBOOT_ARM_HOOKS_H
9
+#define ETHERBOOT_ARM_HOOKS_H
10
+
11
+struct Elf_Bhdr;
12
+
13
+#define arch_main(data, params) do {} while(0)
14
+//void arch_main(in_call_data_t *data, va_list params);
15
+
16
+#define arch_on_exit(status) do {} while(0)
17
+//void arch_on_exit(int status);
18
+
19
+#define arch_relocate_to(addr) do {} while(0)
20
+//void arch_relocate_to(unsigned long addr);
21
+
22
+#define arch_relocated_from(old_addr) do {} while(0)
23
+//void arch_relocate_from(unsigned long old_addr);
24
+
25
+#endif /* ETHERBOOT_ARM_HOOKS_H */

+ 27
- 0
src/arch/armnommu/include/io.h View File

@@ -0,0 +1,27 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ETHERBOOT_IO_H
9
+#define ETHERBOOT_IO_H
10
+
11
+#define virt_to_phys(vaddr)	((unsigned long) (vaddr))
12
+#define phys_to_virt(vaddr)	((void *) (vaddr))
13
+
14
+#define virt_to_bus virt_to_phys
15
+#define bus_to_virt phys_to_virt
16
+
17
+#define iounmap(addr)				((void)0)
18
+#define ioremap(physaddr, size)			(physaddr)
19
+
20
+extern unsigned char inb (unsigned long int port);
21
+extern unsigned short int inw (unsigned long int port);
22
+extern unsigned long int inl (unsigned long int port);
23
+extern void outb (unsigned char value, unsigned long int port);
24
+extern void outw (unsigned short value, unsigned long int port);
25
+extern void outl (unsigned long value, unsigned long int port);
26
+
27
+#endif /* ETHERBOOT_IO_H */

+ 15
- 0
src/arch/armnommu/include/latch.h View File

@@ -0,0 +1,15 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef LATCH_H
9
+#define LATCH_H
10
+
11
+// Freerun_Timer is always at 12.288 MHZ
12
+#define TICKS_PER_SEC		(12288000UL)
13
+//#define TICKS_PER_SEC		(73728000UL)
14
+
15
+#endif /* LATCH_H */

+ 43
- 0
src/arch/armnommu/include/limits.h View File

@@ -0,0 +1,43 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef __LIMITS_H
9
+#define __LIMITS_H  1
10
+
11
+#define MB_LEN_MAX	16
12
+
13
+#define CHAR_BIT	8
14
+
15
+#define SCHAR_MIN	(-128)
16
+#define SCHAR_MAX	127
17
+
18
+#define UCHAR_MAX	255
19
+
20
+#define CHAR_MIN	SCHAR_MIN
21
+#define CHAR_MAX	SCHAR_MAX
22
+
23
+#define SHRT_MIN	(-32768)
24
+#define SHRT_MAX	32767
25
+
26
+#define USHRT_MAX	65535
27
+
28
+#define INT_MIN	(-INT_MAX - 1)
29
+#define INT_MAX	2147483647
30
+
31
+#define UINT_MAX	4294967295U
32
+
33
+#define LONG_MAX	2147483647L
34
+#define LONG_MIN	(-LONG_MAX - 1L)
35
+
36
+#define ULONG_MAX	4294967295UL
37
+
38
+#define LLONG_MAX	9223372036854775807LL
39
+#define LLONG_MIN	(-LLONG_MAX - 1LL)
40
+
41
+#define ULLONG_MAX	18446744073709551615ULL
42
+
43
+#endif

+ 30
- 0
src/arch/armnommu/include/lxt971a.h View File

@@ -0,0 +1,30 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+
9
+/*
10
+ * Intel LXT971ALE (MII-compatible PHY)
11
+ */
12
+
13
+#define Adr_LXT971A_Control		0	/* Control Register */
14
+#define Adr_LXT971A_Status1		1	/* MII Status Register #1 */
15
+#define Adr_LXT971A_PHY_ID1		2	/* PHY Identification Register 1 */
16
+#define Adr_LXT971A_PHY_ID2		3	/* PHY Identification Register 2 */
17
+#define Adr_LXT971A_AN_Advertise	4	/* Auto Negotiation Advertisement Register */
18
+#define Adr_LXT971A_AN_Link_Ability	5	/* Auto Negotiation Link Partner Base Page Ability Register */
19
+#define Adr_LXT971A_AN_Expansion	6	/* Auto Negotiation Expansion */
20
+#define Adr_LXT971A_AN_Next_Page_Txmit	7	/* Auto Negotiation Next Page Transmit Register */
21
+#define Adr_LXT971A_AN_Link_Next_Page	8	/* Auto Negotiation Link Partner Next Page Receive Register */
22
+#define Adr_LXT971A_Fast_Control	9	/* Not Implemented */
23
+#define Adr_LXT971A_Fast_Status		10	/* Not Implemented */
24
+#define Adr_LXT971A_Extended_Status	15	/* Not Implemented */
25
+#define Adr_LXT971A_Port_Config		16	/* Configuration Register */
26
+#define Adr_LXT971A_Status2		17	/* Status Register #2 */
27
+#define Adr_LXT971A_Interrupt_Enable	18	/* Interrupt Enable Register */
28
+#define Adr_LXT971A_Interrupt_Status	19	/* Interrupt Status Register */
29
+#define Adr_LXT971A_LED_Config		20	/* LED Configuration Register */
30
+#define Adr_LXT971A_Transmit_Control	30	/* Transmit Control Register */

+ 23
- 0
src/arch/armnommu/include/setjmp.h View File

@@ -0,0 +1,23 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef ETHERBOOT_SETJMP_H
9
+#define ETHERBOOT_SETJMP_H
10
+
11
+#ifndef __ASSEMBLER__
12
+/* Jump buffer contains v1-v6, sl, fp, sp and pc.  Other registers are not
13
+   saved.  */
14
+//typedef int jmp_buf[22];
15
+typedef int jmp_buf[10];
16
+#endif
17
+
18
+extern int sigsetjmp(jmp_buf __env, int __savemask);
19
+extern void longjmp(jmp_buf __env, int __val) __attribute__((__noreturn__));
20
+
21
+#define setjmp(env) sigsetjmp(env,0)
22
+
23
+#endif /* ETHERBOOT_SETJMP_H */

+ 23
- 0
src/arch/armnommu/include/stdint.h View File

@@ -0,0 +1,23 @@
1
+/*
2
+ *  Copyright (C) 2004 Tobias Lorenz
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License version 2 as
6
+ * published by the Free Software Foundation.
7
+ */
8
+#ifndef STDINT_H
9
+#define STDINT_H
10
+
11
+typedef unsigned long      size_t;
12
+
13
+typedef unsigned char      uint8_t;
14
+typedef unsigned short     uint16_t;
15
+typedef unsigned long      uint32_t;
16
+typedef unsigned long long uint64_t;
17
+
18
+typedef signed char        int8_t;
19
+typedef signed short       int16_t;
20
+typedef signed int         int32_t;
21
+typedef signed long long   int64_t;
22
+
23
+#endif /* STDINT_H */

+ 7
- 0
src/arch/e1/Config View File

@@ -0,0 +1,7 @@
1
+# Config for e1 Etherboot
2
+#
3
+
4
+CFLAGS+= -mgnu-param -DCONSOLE_SERIAL -DCOMCONSOLE=0x01C00000 -DCONSPEED=28800 
5
+CFLAGS+= -DSIZEINDICATOR  -DNO_DHCP_SUPPORT -DBAR_PROGRESS
6
+#CFLAGS+= -DEMBEDDED -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
7
+

+ 70
- 0
src/arch/e1/Makefile View File

@@ -0,0 +1,70 @@
1
+ARCH_FORMAT=	coff-e1
2
+
3
+BUILD_ROMS=	$(ROMS)
4
+BUILD_COFFS=	$(patsubst %img, %coff, $(IMGS))
5
+SUFFIXES+=	rom zrom coff
6
+
7
+CC=		e1-coff-gcc
8
+AS=		e1-coff-as
9
+LD=		e1-coff-ld
10
+SIZE=	e1-coff-size
11
+AR=		e1-coff-ar
12
+RANLIB=	e1-coff-ranlib
13
+OBJCOPY=e1-coff-objcopy
14
+
15
+# DMAC_HW_ADDR_DRV holds the ethernet's MAC address. It is passed as
16
+# flag to the low level driver instead of reading it from an 
17
+# external EEPROM, which we do not have!
18
+EXTRA_CFLAGS = -DEMBEDDED -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
19
+
20
+START=	$(BIN)/start.o
21
+START16=	$(BIN)/start.o
22
+
23
+SRCS+=	arch/e1/core/e132_xs.c
24
+SRCS+=	arch/e1/core/e1_timer.c
25
+SRCS+=	arch/e1/core/longjmp.c
26
+SRCS+=	arch/e1/core/memcmp.S
27
+SRCS+=	arch/e1/core/memcpy.S
28
+SRCS+=	arch/e1/core/memset.S
29
+SRCS+=	arch/e1/core/setjmp.c
30
+SRCS+=	arch/e1/core/strcmp.S
31
+SRCS+=	arch/e1/core/start.S
32
+
33
+ROMLIMIT:=3276800
34
+
35
+include		$(BIN)/Roms
36
+
37
+ROMS= $(BIN)/cs89x0.rom
38
+IMGS= $(BIN)/cs89x0.img
39
+
40
+#allfiles:	$(BUILD_ROMS)
41
+all:	$(BUILD_COFFS)
42
+
43
+BOBJS+=		$(BIN)/e1_timer.o
44
+BOBJS+=		$(BIN)/memcmp.o $(BIN)/memcpy.o $(BIN)/memset.o
45
+BOBJS+=		$(BIN)/setjmp.o $(BIN)/longjmp.o 
46
+BOBJS+=		$(BIN)/e132_xs.o
47
+
48
+# Utilities
49
+
50
+$(BIN)/nrv2b:	util/nrv2b.c
51
+	$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
52
+
53
+# Pattern Rules
54
+# General for compiling/assembly source files
55
+$(BIN)/cs89x0.o:	drivers/net/cs89x0.c $(MAKEDEPS)
56
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
57
+# With the current tools we have problem with the compilation 
58
+# of the vsprintf file when the -O2 is selected. So we compile 
59
+# the aforemntioned file with -O1 !!!
60
+$(BIN)/vsprintf.o:	core/vsprintf.c $(MAKEDEPS)
61
+	$(CC) $(CFLAGS) -O1 -o $@ -c $<
62
+
63
+$(BIN)/%.o:	arch/e1/core/%.c $(MAKEDEPS)
64
+	$(CC) $(CFLAGS) -o $@ -c $<
65
+
66
+$(BIN)/%.o:	arch/e1/core/%.S $(MAKEDEPS)
67
+	$(CPP) $(CFLAGS) -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
68
+
69
+$(BIN)/%.coff:	$(BIN)/%.tmp $(MAKEDEPS)
70
+	mv $< $(BIN)/etherboot.coff

+ 67
- 0
src/arch/e1/Makefile.working View File

@@ -0,0 +1,67 @@
1
+ARCH_FORMAT=	coff-e1
2
+
3
+CC=		e1-coff-gcc
4
+AS=		e1-coff-as
5
+LD=		e1-coff-ld
6
+SIZE=	e1-coff-size
7
+AR=		e1-coff-ar
8
+RANLIB=	e1-coff-ranlib
9
+OBJCOPY=e1-coff-objcopy
10
+
11
+EXTRA_CFLAGS = -DEMBEDDED -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
12
+
13
+BUILD_ROMS=	$(ROMS)
14
+BUILD_COFFS=	$(BIN)/cs89x0.coff
15
+#BUILD_COFFS=	$(patsubst %img, %coff, $(IMGS))
16
+
17
+START=	$(BIN)/start.o
18
+START16=	$(BIN)/start.o
19
+
20
+#SRCS+=	arch/e1/core/coff_loader.c
21
+SRCS+=	arch/e1/core/e132_xs.c
22
+SRCS+=	arch/e1/core/e1_timer.c
23
+SRCS+=	arch/e1/core/longjmp.c
24
+SRCS+=	arch/e1/core/memcmp.S
25
+SRCS+=	arch/e1/core/memcpy.S
26
+SRCS+=	arch/e1/core/memset.S
27
+SRCS+=	arch/e1/core/setjmp.c
28
+SRCS+=	arch/e1/core/strcmp.S
29
+SRCS+=	arch/e1/core/start.S
30
+
31
+ROMLIMIT:=3276800
32
+
33
+include		$(BIN)/Roms
34
+
35
+hyperstone:		$(BUILD_COFFS)
36
+coff:		$(BUILD_COFFS)
37
+
38
+BOBJS+=		$(BIN)/e1_timer.o
39
+BOBJS+=		$(BIN)/memcmp.o $(BIN)/memcpy.o $(BIN)/memset.o
40
+BOBJS+=		$(BIN)/setjmp.o $(BIN)/longjmp.o 
41
+BOBJS+=		$(BIN)/e132_xs.o
42
+
43
+# Utilities
44
+
45
+$(BIN)/nrv2b:	util/nrv2b.c
46
+	$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
47
+
48
+# Pattern Rules
49
+# General for compiling/assembly source files
50
+
51
+$(BIN)/cs89x0.o:	drivers/net/cs89x0.c $(MAKEDEPS)
52
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
53
+# With the current tools we have problem with the compilation 
54
+# of the vsprintf file when the -O2 is selected. So we compile 
55
+# the aforemntioned file with -O1 !!!
56
+$(BIN)/vsprintf.o:	core/vsprintf.c $(MAKEDEPS)
57
+	$(CC) $(CFLAGS) -O1 -o $@ -c $<
58
+
59
+$(BIN)/%.o:	arch/e1/core/%.c $(MAKEDEPS)
60
+	$(CC) $(CFLAGS) -o $@ -c $<
61
+
62
+$(BIN)/%.o:	arch/e1/core/%.S $(MAKEDEPS)
63
+	$(CPP) $(CFLAGS) -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
64
+
65
+$(BIN)/%.coff:	$(BIN)/%.tmp $(MAKEDEPS)
66
+	mv $< $(BIN)/etherboot.coff
67
+

+ 80
- 0
src/arch/e1/README View File

@@ -0,0 +1,80 @@
1
+Introduction
2
+---------------------
3
+This README file provides guideliness to compile successfully the 
4
+Etherboot for Hyperstone.
5
+This directory (src/arch/e1) contains the files that depend on 
6
+Hyperstone's architecture. The header files that include the 
7
+configuration of the system are based on Hyperstone's E132-XS 
8
+development board. The can be very easily modified to support 
9
+anyother configuration environment. 
10
+
11
+Software Perquisites:
12
+---------------------
13
+The build environment requires a C compiler for the E1-32XS
14
+processor. Normally you can simply install a cross-compiling tool
15
+chain based on the GNU tools (that is binutils and gcc). If you
16
+are running a Linux system on a x86 CPU then you can just download
17
+the toolchain as a binary from Hyperstone's official web-site. The
18
+binary distribution will untar the tools in the /usr/local/e1-coff
19
+directory. On any other system you will need to build the tool
20
+chain from the sources.
21
+
22
+To compile successfully the following tools should be available:
23
+ - GNU toolchain:
24
+    - GCC ver 2.95.2 20030110 (release)         e1-coff-gcc -v
25
+    - LD ver 2.12.90 20020726                   e1-coff-ld -V
26
+
27
+Hardware Perquisites:
28
+---------------------
29
+The etherboot has been successfully tested in the E1-32XS
30
+development board. A second serial device is initialized
31
+to act as a console. The standard messages
32
+are redirected to the console. Nevertheless, if one wants not
33
+to use the serial console he may omit the corresponding switches
34
+from the Config file located under "src/arch/e1/" directory.
35
+
36
+On the E1-32XS board that was  used, a daughter-board was employed
37
+to connect a second HyIce to the development board. Since the HyIce
38
+embeds a standard 16550 device, the Etherboot's standard device 
39
+driver is used.
40
+
41
+The position of the jumpers of the development board in order to
42
+initialize both the second HyIce and the Ethernet device is
43
+depicted in the following table:
44
+
45
+Jumper: Position
46
+------:--------------
47
+J3      1-2 (default)
48
+J4      1-2 (default)
49
+J13     5-6
50
+J5      1-2 (default)
51
+J6      1-2 & 3-4
52
+J7      3-4
53
+J9      1-2 (default)
54
+J10     1-2
55
+J11     3-4
56
+
57
+Compilation
58
+---------------------
59
+In order to compile Etherboot for Hyperstone, the following steps should be followed:
60
+1) Edit the main Makefile (located under "src" directory") and comment-out
61
+the ARCH variable (by putting a "#" in front of it). Append the following line:
62
+ARCH:=e1
63
+2) Edit the Config file (the one located under "src" directory) and make sure that
64
+the CFLAGS variable will contain *only* the following swithces:
65
+CFLAGS+=	-DCONFIG_ISA
66
+CFLAGS+=	-DBOOT_FIRST=BOOT_NIC
67
+CFLAGS+=	-DALLOW_ONLY_ENCAPSULATED
68
+CFLAGS+=	-DBACKOFF_LIMIT=7 -DCONGESTED
69
+CFLAGS+=	-DCOFF_IMAGE 
70
+CFLAGS+=	-DDOWNLOAD_PROTO_TFTP
71
+Please note that extra or any other switches may cause failure of compilation!
72
+3) type "make hyperstone" or "make coff"
73
+4) the generated file will be located under the "src/bin" directory and will be called :
74
+ "etherboot.coff". Now you may download it with usual way using e1-coff-gdb ..
75
+
76
+Have Fun
77
+
78
+Yannis Mitsos, George Thanos
79
+{gmitsos,gthanos}@telecom.ntua.gr
80
+

+ 176
- 0
src/arch/e1/core/coff_loader.c View File

@@ -0,0 +1,176 @@
1
+/*
2
+ * Copyright 2003 Yannis Mitsos and George Thanos 
3
+ * {gmitsos@gthanos}@telecom.ntua.gr
4
+ * Released under GPL2, see the file COPYING in the top directory
5
+ * COFF loader is based on the source code of the ELF loader.
6
+ *
7
+ */
8
+#include "coff.h"
9
+
10
+#define COFF_DEBUG 0
11
+
12
+typedef struct {
13
+	COFF_filehdr coff32;
14
+	COFF_opthdr	opthdr32;
15
+	union {
16
+		COFF_scnhdr scnhdr32[1];
17
+		unsigned char dummy[1024];
18
+	} p;
19
+	unsigned long curaddr;
20
+	signed int segment;		/* current segment number, -1 for none */
21
+	unsigned int loc;		/* start offset of current block */
22
+	unsigned int skip;		/* padding to be skipped to current segment */
23
+	unsigned long toread;	/* remaining data to be read in the segment */
24
+}coff_state;
25
+
26
+coff_state cstate;
27
+
28
+static sector_t coff32_download(unsigned char *data, unsigned int len, int eof);
29
+static inline os_download_t coff_probe(unsigned char *data, unsigned int len)
30
+{
31
+	unsigned long phdr_size;
32
+
33
+	if (len < (sizeof(cstate.coff32)+ sizeof(cstate.opthdr32))) {
34
+		return 0;
35
+	}
36
+	memcpy(&cstate.coff32, data, (sizeof(cstate.coff32)+sizeof(cstate.opthdr32)));
37
+
38
+	if ((cstate.coff32.f_magic != EM_E1) ||
39
+	  	(cstate.opthdr32.magic != O_MAGIC)){
40
+		return 0;
41
+	}
42
+	printf("(COFF");
43
+	printf(")... \n");
44
+
45
+	if (cstate.coff32.f_opthdr == 0){
46
+		printf("No optional header in COFF file, cannot find the entry point\n");
47
+                return dead_download;
48
+	}
49
+
50
+	phdr_size = cstate.coff32.f_nscns * sizeof(cstate.p.scnhdr32);
51
+	if (sizeof(cstate.coff32) +  cstate.coff32.f_opthdr + phdr_size > len) {
52
+		printf("COFF header outside first block\n");
53
+                return dead_download;
54
+	}
55
+
56
+	memcpy(&cstate.p.scnhdr32, data + (sizeof(cstate.coff32) +  cstate.coff32.f_opthdr), phdr_size);
57
+
58
+	/* Check for Etherboot related limitations.  Memory
59
+	 * between _text and _end is not allowed.
60
+	 * Reasons: the Etherboot code/data area.
61
+	 */
62
+	for (cstate.segment = 0; cstate.segment < cstate.coff32.f_nscns; cstate.segment++) {
63
+		unsigned long start, mid, end, istart, iend;
64
+
65
+		if ((cstate.p.scnhdr32[cstate.segment].s_flags != S_TYPE_TEXT) && 
66
+			(cstate.p.scnhdr32[cstate.segment].s_flags != S_TYPE_DATA) && 
67
+			(cstate.p.scnhdr32[cstate.segment].s_flags != S_TYPE_BSS)){ /* Do we realy need to check the BSS section ? */
68
+#ifdef COFF_DEBUG
69
+				printf("Section <%s> in not a loadable section \n",cstate.p.scnhdr32[cstate.segment].s_name);
70
+#endif
71
+			continue;
72
+		}
73
+
74
+	start = cstate.p.scnhdr32[cstate.segment].s_paddr;
75
+	mid = start + cstate.p.scnhdr32[cstate.segment].s_size;
76
+	end = start + cstate.p.scnhdr32[cstate.segment].s_size;
77
+
78
+	/* Do we need the following variables ? */
79
+	istart = 0x8000;
80
+	iend = 0x8000;
81
+
82
+		if (!prep_segment(start, mid, end, istart, iend)) {
83
+                	return dead_download;
84
+		}
85
+}
86
+	cstate.segment = -1;
87
+	cstate.loc = 0;
88
+	cstate.skip = 0;
89
+	cstate.toread = 0;
90
+	return coff32_download;
91
+}
92
+
93
+extern int mach_boot(unsigned long entry_point);
94
+static sector_t coff32_download(unsigned char *data, unsigned int len, int eof)
95
+{
96
+	unsigned long skip_sectors = 0;
97
+	unsigned int offset;	/* working offset in the current data block */
98
+	int i;
99
+
100
+	offset = 0;
101
+	do {
102
+		if (cstate.segment != -1) {
103
+			if (cstate.skip) {
104
+				if (cstate.skip >= len - offset) {
105
+					cstate.skip -= len - offset;
106
+					break;
107
+				}
108
+				offset += cstate.skip;
109
+				cstate.skip = 0;
110
+			}
111
+			
112
+			if (cstate.toread) {
113
+				unsigned int cplen;
114
+				cplen = len - offset;
115
+				if (cplen >= cstate.toread) {
116
+					cplen = cstate.toread;
117
+				}
118
+				memcpy(phys_to_virt(cstate.curaddr), data+offset, cplen);
119
+				cstate.curaddr += cplen;
120
+				cstate.toread -= cplen;
121
+				offset += cplen;
122
+				if (cstate.toread)
123
+					break;
124
+			}
125
+		}
126
+	
127
+		/* Data left, but current segment finished - look for the next
128
+		 * segment (in file offset order) that needs to be loaded. 
129
+		 * We can only seek forward, so select the program headers,
130
+		 * in the correct order.
131
+		 */
132
+		cstate.segment = -1;
133
+		for (i = 0; i < cstate.coff32.f_nscns; i++) {
134
+
135
+			if ((cstate.p.scnhdr32[i].s_flags != S_TYPE_TEXT) && 
136
+			(cstate.p.scnhdr32[i].s_flags != S_TYPE_DATA))
137
+				continue;
138
+			if (cstate.p.scnhdr32[i].s_size == 0)
139
+				continue;
140
+			if (cstate.p.scnhdr32[i].s_scnptr < cstate.loc + offset)
141
+				continue;	/* can't go backwards */
142
+			if ((cstate.segment != -1) &&
143
+				(cstate.p.scnhdr32[i].s_scnptr >= cstate.p.scnhdr32[cstate.segment].s_scnptr))
144
+				continue;	/* search minimum file offset */
145
+			cstate.segment = i;
146
+		}
147
+
148
+		if (cstate.segment == -1) {
149
+			/* No more segments to be loaded, so just start the
150
+			 * kernel.  This saves a lot of network bandwidth if
151
+			 * debug info is in the kernel but not loaded.  */
152
+			goto coff_startkernel;
153
+			break;
154
+		}
155
+		cstate.curaddr = cstate.p.scnhdr32[cstate.segment].s_paddr;
156
+		cstate.skip	   = cstate.p.scnhdr32[cstate.segment].s_scnptr - (cstate.loc + offset);
157
+		cstate.toread  = cstate.p.scnhdr32[cstate.segment].s_size;
158
+#if COFF_DEBUG
159
+		printf("PHDR %d, size %#lX, curaddr %#lX\n",
160
+			cstate.segment, cstate.toread, cstate.curaddr);
161
+#endif
162
+	} while (offset < len);
163
+
164
+	cstate.loc += len + (cstate.skip & ~0x1ff);
165
+	skip_sectors = cstate.skip >> 9;
166
+	cstate.skip &= 0x1ff;
167
+	
168
+	if (eof) {
169
+		unsigned long entry;
170
+coff_startkernel:
171
+		entry = cstate.opthdr32.entry;
172
+		done();
173
+		mach_boot(entry);
174
+	}
175
+	return skip_sectors;
176
+}

+ 70
- 0
src/arch/e1/core/e132_xs.c View File

@@ -0,0 +1,70 @@
1
+/*
2
+ * Copyright 2003 Yannis Mitsos and George Thanos 
3
+ * {gmitsos@gthanos}@telecom.ntua.gr
4
+ * Released under GPL2, see the file COPYING in the top directory
5
+ *
6
+ */
7
+#include "hooks.h"
8
+#include "io.h"
9
+#include "etherboot.h"
10
+#include "e132_xs_board.h"
11
+
12
+unsigned int io_periph[NR_CS] = {[0 ... NR_CS-1] = 0 };
13
+
14
+/*
15
+void arch_main(struct Elf_Bhdr *ptr __unused)
16
+{
17
+
18
+}
19
+*/
20
+
21
+void init_peripherals(void)
22
+{
23
+	int i;
24
+
25
+	for(i=0; i< NR_CS; i++){
26
+		io_periph[i]= (SLOW_IO_ACCESS | i << 22);
27
+	}
28
+
29
+	io_periph[ETHERNET_CS] = (io_periph[ETHERNET_CS] | 1 << IOWait);
30
+
31
+	asm volatile("
32
+			ori SR, 0x20
33
+			movi FCR, 0x66ffFFFF"
34
+			:
35
+			:);
36
+}
37
+
38
+struct meminfo meminfo;
39
+void get_memsizes(void)
40
+{
41
+/* We initialize the meminfo structure 
42
+ * according to our development board's specs
43
+ * We do not have a way to automatically probe the 
44
+ * memspace instead we initialize it manually
45
+ */
46
+	meminfo.basememsize = BASEMEM;
47
+	meminfo.memsize = 	SDRAM_SIZE;
48
+	meminfo.map_count = NR_MEMORY_REGNS;
49
+
50
+	meminfo.map[0].addr = SDRAM_BASEMEM;
51
+	meminfo.map[0].size = SDRAM_SIZE;
52
+	meminfo.map[0].type = E820_RAM;
53
+	meminfo.map[1].addr = SRAM_BASEMEM;
54
+	meminfo.map[1].size = SRAM_SIZE;
55
+	meminfo.map[1].type = E820_RAM;
56
+	meminfo.map[2].addr = IRAM_BASEMEM;
57
+	meminfo.map[2].size = IRAM_SIZE;
58
+	meminfo.map[2].type = E820_RAM;
59
+}
60
+
61
+int mach_boot(register unsigned long entry_point)
62
+{
63
+		asm volatile(
64
+					 "mov PC, %0"
65
+					: /* no outputs */
66
+					: "l" (entry_point) );
67
+		return 0; /* We should never reach this point ! */
68
+
69
+}
70
+

+ 94
- 0
src/arch/e1/core/e1_timer.c View File

@@ -0,0 +1,94 @@
1
+/*
2
+ * Copyright 2003 Yannis Mitsos and George Thanos 
3
+ * {gmitsos@gthanos}@telecom.ntua.gr
4
+ * Released under GPL2, see the file COPYING in the top directory
5
+ *
6
+ */
7
+#include "etherboot.h"
8
+#include "timer.h"
9
+#include "e132_xs_board.h"
10
+
11
+/* get timer returns the contents of the timer */
12
+static inline unsigned long get_timer(void)
13
+{
14
+	unsigned long result;
15
+	__asm__ __volatile__("
16
+					ORI	SR, 0x20
17
+					mov	%0, TR" 
18
+					: "=l"(result));
19
+	return result;
20
+}
21
+
22
+/* ------ Calibrate the TSC ------- 
23
+ * Time how long it takes to excute a loop that runs in known time.
24
+ * And find the convertion needed to get to CLOCK_TICK_RATE
25
+ */
26
+
27
+static unsigned long configure_timer(void)
28
+{
29
+	unsigned long TPR_value; /* Timer Prescalar Value */
30
+
31
+	TPR_value = 0x000C00000;
32
+	
33
+	asm volatile (" 
34
+				FETCH   4	
35
+				ORI		SR, 0x20
36
+				MOV		TPR, %0
37
+				ORI		SR, 0x20
38
+				MOVI	TR, 0x0"
39
+				: /* no outputs */
40
+				: "l" (TPR_value)
41
+				); 
42
+
43
+	printf("The time prescaler register is set to: <%#x>\n",TPR_value);
44
+	return (1);
45
+}
46
+
47
+static unsigned long clocks_per_tick;
48
+
49
+void setup_timers(void)
50
+{
51
+	if (!clocks_per_tick) {
52
+		clocks_per_tick = configure_timer();
53
+	}
54
+}
55
+
56
+unsigned long currticks(void)
57
+{
58
+	return get_timer()/clocks_per_tick;
59
+}
60
+
61
+static unsigned long timer_timeout;
62
+static int __timer_running(void)
63
+{
64
+	return get_timer() < timer_timeout;
65
+}
66
+
67
+void udelay(unsigned int usecs)
68
+{
69
+	unsigned long now;
70
+	now = get_timer();
71
+	timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
72
+	while(__timer_running());
73
+}
74
+void ndelay(unsigned int nsecs)
75
+{
76
+	unsigned long now;
77
+	now = get_timer();
78
+	timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
79
+	while(__timer_running());
80
+}
81
+
82
+void load_timer2(unsigned int timer2_ticks)
83
+{
84
+	unsigned long now;
85
+	unsigned long clocks;
86
+	now = get_timer();
87
+	clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
88
+	timer_timeout = now + clocks;
89
+}
90
+
91
+int timer2_running(void)
92
+{
93
+	return __timer_running();
94
+}

+ 126
- 0
src/arch/e1/core/etherboot.lds View File

@@ -0,0 +1,126 @@
1
+/* Default linker script, for normal executables */
2
+OUTPUT_FORMAT("coff-e1-big")
3
+MEMORY
4
+	{
5
+        romvec   : ORIGIN = 0x2000000,  LENGTH = 0x0000400
6
+        flash    : ORIGIN = 0xE0000000, LENGTH = 0x20000 
7
+        eflash   : ORIGIN = 0x2200000,  LENGTH = 0x20000
8
+        ram      : ORIGIN = 0x00000000, LENGTH = 0x1000000
9
+        eram16MB : ORIGIN = 0x01000000, LENGTH = 0
10
+        sram     : ORIGIN = 0x40000000, LENGTH = 0x40000
11
+		iram     : ORIGIN = 0xC0000000, LENGTH = 0x4000
12
+	}
13
+
14
+SEARCH_DIR("/usr/local/e1-coff/lib");
15
+ENTRY(Main)
16
+MEM0start   = 0x00000000;
17
+MEM0size    = 0x40000000;
18
+MEM1start   = 0x40000000;
19
+MEM1size    = 0x40000000;
20
+MEM2start   = 0x80000000;
21
+MEM2size    = 0x40000000;
22
+IRAMstart   = 0xC0000000;
23
+IRAMsize    = 0x20000000;
24
+MEM3start   = 0xE0000000;
25
+MEM3size    = 0x20000000;
26
+Stack1Reserve = 560;
27
+_Stack1Size = DEFINED(_Stack1Size)? _Stack1Size : 1*1024;
28
+_Stack2Size = DEFINED(_Stack2Size)? _Stack2Size : 16*1024;
29
+_Stack1Base = DEFINED(_Stack1Base)? _Stack1Base : __bss_end__;
30
+_Stack2Base = DEFINED(_Stack2Base)? _Stack2Base : __bss_end__ + _Stack1Size + Stack1Reserve;
31
+_Mem0HeapBase = DEFINED(_Mem0HeapBase)? _Mem0HeapBase : _Stack2Base + _Stack2Size;
32
+_Mem1HeapBase = DEFINED(_Mem1HeapBase)? _Mem1HeapBase : 0;
33
+Priority    = DEFINED(Priority)   ? Priority    : 31;
34
+TextBase    = DEFINED(TextBase)   ? TextBase    : 0xa00000;
35
+SECTIONS
36
+{
37
+  .G6 (DEFINED(G6Base) ? G6Base : 0x9000) : {
38
+    *(.G6)
39
+  }
40
+  .G7 (DEFINED(G7Base) ? G7Base : 0x40001000) : {
41
+    *(.G7)
42
+  }
43
+  .G8 (DEFINED(G8Base) ? G8Base : 0xC0000000) : {
44
+    *(.G8)
45
+  }
46
+  .G9 (DEFINED(G9Base) ? G9Base : 0) : {
47
+    *(.G9)
48
+  }
49
+  .G10 (DEFINED(G10Base) ? G10Base : 0) : {
50
+    *(.G10)
51
+  }
52
+  .G11 (DEFINED(G11Base) ? G11Base : 0) : {
53
+    *(.G11)
54
+  }
55
+  .G12 (DEFINED(G12Base) ? G12Base : 0) : {
56
+    *(.G12)
57
+  }
58
+  .G13 (DEFINED(G13Base) ? G13Base : 0) : {
59
+    *(.G13)
60
+  }
61
+
62
+  .text TextBase : {
63
+	__virt_start = .;
64
+	__text = . ;
65
+    *(.text)
66
+    *(.fini)
67
+ 		. = ALIGN(16);
68
+		_isa_drivers = . ;
69
+		*(.drivisa);
70
+		_isa_drivers_end = . ;
71
+		. = ALIGN(16);
72
+
73
+   *(.init)
74
+  _etext  =  . ;
75
+    /* _init = DEFINED(_init) ? _init : 0; */
76
+    /* _fini = DEFINED(_fini) ? _fini : 0; */
77
+    /* _argc = DEFINED(_argc) ? _argc : 0; */
78
+    /* _argv = DEFINED(_argv) ? _argv : 0; */
79
+    /* _envp = DEFINED(_envp) ? _envp : 0; */
80
+    /* _hwinit = DEFINED(_hwinit) ? _hwinit : 0; */
81
+    /* _atexit = DEFINED(_atexit) ? _atexit : 0; */
82
+    G6Size = SIZEOF(.G6);
83
+    G7Size = SIZEOF(.G7);
84
+    G8Size = SIZEOF(.G8);
85
+    G9Size = SIZEOF(.G9);
86
+    G10Size = SIZEOF(.G10);
87
+    G11Size = SIZEOF(.G11);
88
+    G12Size = SIZEOF(.G12);
89
+    G13Size = SIZEOF(.G13);
90
+
91
+}
92
+
93
+  .data  SIZEOF(.text) + ADDR(.text) : {
94
+    *(.data)
95
+     _edata  =  . ;
96
+}
97
+
98
+  .bss  SIZEOF(.data) + ADDR(.data) : 
99
+  {
100
+     __bss_start__ = ALIGN( 0x10 ) ;
101
+     __bss = . ;
102
+    *(.bss)
103
+    *(COMMON)
104
+     __end = . ;
105
+     __bss_end__ = ALIGN( 0x10 ) ;
106
+     __ebss = . ;
107
+  }
108
+
109
+.eram16MB :    
110
+	{
111
+	___ramend = . - 0x7000;
112
+	} > eram16MB
113
+
114
+  .stab  0 (NOLOAD) :
115
+  {
116
+    [ .stab ]
117
+  }
118
+  .stabstr  0 (NOLOAD) :
119
+  {
120
+    [ .stabstr ]
121
+  }
122
+  _GOT_  0 (NOLOAD) :
123
+  {
124
+    [ _GOT_ ]
125
+  }
126
+}

+ 35
- 0
src/arch/e1/core/longjmp.c View File

@@ -0,0 +1,35 @@
1
+/*
2
+ * Copyright 2003 Yannis Mitsos and George Thanos 
3
+ * {gmitsos@gthanos}@telecom.ntua.gr
4
+ * Released under GPL2, see the file COPYING in the top directory
5
+ *
6
+ */
7
+#include "setjmp.h"
8
+
9
+unsigned long jmpbuf_ptr;
10
+
11
+void longjmp(jmp_buf state, int value )
12
+{
13
+	if(!value)
14
+		state->__jmpbuf->ReturnValue = 1;
15
+	else
16
+		state->__jmpbuf->ReturnValue = value;
17
+
18
+	jmpbuf_ptr = (unsigned long)state; 
19
+
20
+#define _state_ ((struct __jmp_buf_tag*)jmpbuf_ptr)
21
+	asm volatile("mov L0, %0\n\t"
22
+		     "mov L1, %1\n\t"
23
+		     "mov L2, %2\n\t"
24
+		     "mov G3, %3\n\t"
25
+		     "mov G4, %4\n\t"
26
+		     "ret PC, L1\n\t"
27
+		     :/*no output*/
28
+		     :"l"(_state_->__jmpbuf->ReturnValue),
29
+		      "l"(_state_->__jmpbuf->SavedPC),
30
+		      "l"(_state_->__jmpbuf->SavedSR),
31
+		      "l"(_state_->__jmpbuf->G3),
32
+		      "l"(_state_->__jmpbuf->G4)
33
+		     :"%G3", "%G4", "%L0", "%L1" );
34
+#undef _state_
35
+}

+ 54
- 0
src/arch/e1/core/memcmp.S View File

@@ -0,0 +1,54 @@
1
+/*
2
+ * Derived from the Hyperstone's library source code.
3
+ * Modefied src in order to apply the -mgnu-param compiler option.
4
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
5
+ *                              George Thanos <gthanos@telecom.ntua.gr>
6
+ */
7
+	    .text
8
+	    .align   2
9
+	    .global  _memcmp
10
+
11
+;ENTRY (_memcmp)
12
+_memcmp:
13
+	    FRAME    L9, L3                 # get incoming parameters
14
+	    CMPBI    L2,3                   # check word alignment
15
+	    BNZ      byte_compare
16
+	    CMPBI    L1,3                   # check word alignment
17
+	    BNZ      byte_compare
18
+
19
+double_compare:
20
+	    ADDI     L0, -8
21
+	    BLT      is_equal
22
+	    LDD.P    L1, L5
23
+	    LDD.P    L2, L7
24
+	    SUB      L5, L7
25
+	    DBNZ     corr_8
26
+	    SUB      L6, L8
27
+	    BZ       double_compare
28
+	    ADDI     L0, 4
29
+	    ADDI     L2, -4
30
+	    ADDI     L1, -4
31
+	    BR       byte_compare
32
+
33
+corr_8:     ADDI     L0, 8
34
+	    ADDI     L2, -8
35
+	    ADDI     L1, -8
36
+byte_compare:
37
+	    ADDI     L0, -1
38
+	    BLT      equal
39
+	    LDBU.N   L2, L5, 1              # Load and compare bytes
40
+	    LDBU.N   L1, L6, 1
41
+	    SUB      L5, L6
42
+	    BZ       byte_compare
43
+	    MOV      L2, L5
44
+	    RET      PC, L3
45
+
46
+is_equal:   CMPI     L0, -8
47
+	    DBNE     byte_compare
48
+	    ADDI     L0, 8
49
+equal:
50
+	    MOVI     L2, 0
51
+	    RET      PC, L3
52
+
53
+	    .END
54
+

+ 79
- 0
src/arch/e1/core/memcpy.S View File

@@ -0,0 +1,79 @@
1
+/*
2
+ * Derived from the Hyperstone's library source code.
3
+ * Modefied src in order to apply the -mgnu-param compiler option.
4
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
5
+ *                              George Thanos <gthanos@telecom.ntua.gr>
6
+ */    
7
+		.text
8
+	    .align   2
9
+	    .global  _memcpy
10
+;ENTRY(_memcpy)
11
+_memcpy:
12
+	    FRAME    L8, L3
13
+	    MOV      L7, L2                 # Save for return
14
+
15
+#*****************************
16
+# Perform byte copy if both
17
+# not on a word alignment
18
+#*****************************
19
+	    CMPBI    L2, 3                  # check word alignment
20
+            BNZ      mem_except
21
+	    CMPBI    L1, 3                  # check word alignment
22
+            BNZ      mem_except
23
+
24
+#*****************************
25
+# Copy Double,Word,Halfword,
26
+# then byte
27
+#*****************************
28
+DBL_LOOP:
29
+	    CMPI     L0, 8                  # Copy Doubles
30
+            BLT      DO_WORD
31
+            LDD.P    L1, L5
32
+            ADDI     L0, -8
33
+            DBR      DBL_LOOP
34
+            STD.P    L2, L5
35
+
36
+DO_WORD:
37
+	   CMPI      L0, 4                  # Copy leftover word
38
+           BLT       DO_HALF
39
+	   LDW.P     L1, L5
40
+           ADDI      L0, -4
41
+	   DBZ       DONE                   # Done if L0 is 0
42
+           STW.P     L2, L5
43
+
44
+DO_HALF:
45
+	   CMPI      L0, 2                  # Copy leftover byte
46
+           BLT       DO_BYTE
47
+           LDHU.N    L1, L5, 2
48
+           ADDI      L0, -2
49
+	   DBZ       DONE                   # Done if L0 is 0
50
+           STHU.N    L2, L5, 2
51
+
52
+DO_BYTE:
53
+	   CMPI      L0, 1                  # Copy leftover byte
54
+           BLT       DONE
55
+           LDBU.D    L1, L5, 0
56
+           STBU.D    L2, L5, 0
57
+
58
+DONE:                                       # Copy done
59
+	   MOV       L2, L7                 # Return pointer
60
+           RET       PC, L3
61
+
62
+#****************************
63
+# Byte memcpy
64
+#****************************
65
+mem_except:
66
+           DBR       L_5
67
+           MOVI      L6,0
68
+L_3:
69
+	   LDBS.D    L1, L5, 0              # Transfer the byte
70
+           ADDI      L6, 1
71
+           STBS.D    L2, L5, 0
72
+           ADDI      L2, 1
73
+           ADDI      L1, 1
74
+L_5:                                        # Loop test
75
+           CMP       L6, L0
76
+	   BST       L_3
77
+	   MOV       L2, L7                 # Return pointer
78
+	   RET       PC, L3
79
+	   .END

+ 47
- 0
src/arch/e1/core/memset.S View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * Derived from the Hyperstone's library source code.
3
+ * Modefied src in order to apply the -mgnu-param compiler option.
4
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
5
+ *                              George Thanos <gthanos@telecom.ntua.gr>
6
+ */      
7
+		.text
8
+	    .align   2
9
+		.global _memset
10
+
11
+;ENTRY(_memset)
12
+_memset:    FRAME    L9, L3
13
+	    MASK     L5, L1, 0xFF
14
+	    MOV      L8, L2
15
+	    CMPI     L0, 0                  # if n = 0 then return
16
+            BE       retour
17
+
18
+loop0:      CMPBI    L8, 0x3
19
+	    BZ       word_bound
20
+	    ADDI     L0, -1
21
+	    DBNZ     loop0
22
+	    STBU.N   L8, L5, 1
23
+retour:     RET      PC, L3
24
+
25
+word_bound:
26
+	    CMPI     L0, 8
27
+	    DBLT     loop2
28
+	    MOV      L7, L5
29
+	    SHLI     L7, 8
30
+            OR       L5, L7
31
+            MOV      L7, L5
32
+            SHLI     L7, 16
33
+            OR       L5, L7
34
+            MOV      L6, L5
35
+loop1:      ADDI     L0, -8
36
+            CMPI     L0, 8
37
+            DBGE     loop1
38
+	    STD.P    L8, L5
39
+            CMPI     L0, 0
40
+            DBNZ     loop2
41
+	    ANDNI    L5, ~ 0xFF
42
+	    RET      PC, L3
43
+
44
+loop2:      ADDI     L0, -1
45
+	    DBNZ     loop2
46
+	    STBU.N   L8, L5, 1
47
+	    RET      PC, L3

+ 26
- 0
src/arch/e1/core/setjmp.c View File

@@ -0,0 +1,26 @@
1
+/*
2
+ * Copyright 2003 Yannis Mitsos and George Thanos 
3
+ * {gmitsos@gthanos}@telecom.ntua.gr
4
+ * Released under GPL2, see the file COPYING in the top directory
5
+ *
6
+ */
7
+#include "setjmp.h"
8
+
9
+int setjmp( jmp_buf state)
10
+{
11
+	asm volatile(	"mov %0, G3\n\t"           
12
+			"mov %1, G4\n\t" 
13
+			:"=l"(state->__jmpbuf->G3), 
14
+			 "=l"(state->__jmpbuf->G4) 
15
+			:/*no input*/ 
16
+			:"%G3", "%G4" );
17
+
18
+	asm volatile(   "setadr  %0\n\t"
19
+			"mov %1, L1\n\t"
20
+			"mov %2, L2\n\t"
21
+			:"=l"(state->__jmpbuf->SavedSP),
22
+			 "=l"(state->__jmpbuf->SavedPC),
23
+			 "=l"(state->__jmpbuf->SavedSR)
24
+			:/*no input*/);
25
+	return 0;
26
+}

+ 111
- 0
src/arch/e1/core/start.S View File

@@ -0,0 +1,111 @@
1
+/*
2
+ * Derived from the Hyperstone's library source code.
3
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
4
+ *                              George Thanos <gthanos@telecom.ntua.gr>
5
+ */    
6
+	.global	Priority	; Task-Priority
7
+	.global	_Stack1Size	; Size of hardware stack
8
+	.global	_Stack2Size	; Size of aggregate stack
9
+	.global	_Stack1Base	; Base of hardware stack
10
+	.global	_Stack2Base	; Base of aggregate stack
11
+	.global	_Mem0HeapBase	; Base of Heap in Mem0
12
+	.global	_Mem1HeapBase	; Base of Heap in Mem1
13
+
14
+	.global _init_peripherals
15
+	.global	_main
16
+	.global	Main
17
+
18
+	.global	__exit
19
+	.global	__fmode
20
+	.global	__MaxArgCount
21
+
22
+	.text
23
+BasePtrs:
24
+	.weak	G6Base,G7Base,G8Base,G9Base,G10Base,G11Base,G12Base,G13Base
25
+	.long	G6Base,G7Base,G8Base,G9Base,G10Base,G11Base,G12Base,G13Base
26
+BasePtrsEnd:
27
+HeapPtrs:
28
+	.long	_Mem0HeapBase
29
+	.long	_Mem1HeapBase
30
+HeapPtrsEnd:
31
+
32
+__MaxArgCount:
33
+        .long	32
34
+__StandAloneMode:
35
+	.long	0		; 0 indicate stand alone mode
36
+
37
+;============================================================================;
38
+; Startup-Code                                                               ;
39
+;============================================================================;
40
+	.data
41
+
42
+; do not change the order of: __argc,..
43
+__argc:	
44
+	.long  0
45
+__argv:	
46
+	.long  0
47
+__IsShell:
48
+	.long  1
49
+ErrorLevel:
50
+	.long  0
51
+__lab:	
52
+	.long  0
53
+__fmode:
54
+	.long	0x4000		; O_TEXT    attribute
55
+
56
+_isa_drivers:
57
+	.long	0
58
+
59
+_isa_drivers_end:
60
+	.long	0
61
+
62
+
63
+	.text
64
+Main:
65
+StartUp:
66
+	FRAME	L5, L0
67
+	MOVI	L2, __bss_start__	; clear the .bss segment
68
+0:	CMPI	L2, __bss_end__
69
+	BHE	0f
70
+	DBR	0b
71
+	STW.P	L2, 0
72
+0:	SUM     L2, PC, BasePtrs-$	; Load BasePtrs G6-G13
73
+	LDD.P   L2, G6
74
+	LDD.P   L2, G8
75
+;	LDD.P   L2, G10
76
+	LDD.P   L2, G12
77
+	MOVI    L2, 1
78
+	SUM     L3, PC, __StandAloneMode-$
79
+	STW.R   L3, L2
80
+
81
+	;----------------------------------------------------------------;
82
+	; Call main C function                                           ;
83
+	;----------------------------------------------------------------;
84
+2:	LDW.D	PC, L2, __argc - $	; pass count of arguments to main
85
+	LDW.D   PC, L3, __argv - $	; pass pointer array to main
86
+	CALL	L4, PC, _init_peripherals - $ 
87
+	CALL    L4, PC, _main - $	; --> Call Main-Program
88
+	CHK     PC, PC			; trap if execution arrives here
89
+
90
+__exit:
91
+	FRAME   L5, L1
92
+	STW.D   PC, L0, ErrorLevel - $	; Store ERRORLEVEL
93
+
94
+	CHK     PC, PC
95
+	RET     PC, L1
96
+
97
+	.global ___main
98
+___main:
99
+	FRAME   L4, L1
100
+	MOVI    L3, 2
101
+	STW.D   PC, L3, __StandAloneMode-$
102
+	RET     PC, L1		; does not return
103
+
104
+	.section _GOT_
105
+	.long   Main+4		; OnCreate
106
+	.long   Main+8		; OnError
107
+	.long   BasePtrs	; G6
108
+	.long   BasePtrs+4	; G7
109
+	.long   BasePtrs+8	; G8
110
+	
111
+	.END

+ 76
- 0
src/arch/e1/core/strcmp.S View File

@@ -0,0 +1,76 @@
1
+/*
2
+ * Derived from the Hyperstone's library source code.
3
+ * Modefied src in order to apply the -mgnu-param compiler option.
4
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
5
+ *                              George Thanos <gthanos@telecom.ntua.gr>
6
+ */
7
+        .text
8
+	    .align   2
9
+	    .global  _strcmp
10
+;ENTRY(_strcmp)
11
+_strcmp:
12
+	    FRAME    L8,L2
13
+	    CMPBI    L1, 3        # check for word alignment
14
+	    BNZ      str_except
15
+	    CMPBI    L0, 3        # check for word alignment
16
+	    BNZ      str_except
17
+
18
+start:
19
+	    LDD.P    L1, L4       # post inc mode
20
+	    LDD.P    L0, L6       # post inc mode
21
+            CMPBI    L4, ANYBZ
22
+            BE       correct1
23
+            CMP      L4, L6
24
+            BNE      correct1
25
+            CMP      L5, L7
26
+            BNE      correct
27
+            CMPBI    L5, ANYBZ
28
+            BE       correct
29
+            CMPBI    L6, ANYBZ
30
+            BE       correct1
31
+            CMPBI    L7, ANYBZ
32
+            BNE      start
33
+
34
+correct:    MASK     L4, L5, 0xff000000
35
+	    MASK     L6, L7, 0xff000000
36
+            CMP      L4, L6
37
+            BNE      Exit
38
+            SHLI     L5, 8
39
+            CMPI     L4, 0
40
+            DBNE     correct
41
+            SHLI     L7, 8
42
+            MOV      L1, L4
43
+            RET      PC, L2
44
+
45
+Exit:       SUB      L4, L6       # Subtract chars
46
+            SARI     L4, 24
47
+            MOV      L1, L4
48
+            RET      PC, L2
49
+
50
+correct1:   MASK     L5, L4, 0xff000000
51
+	    MASK     L7, L6, 0xff000000
52
+            CMP      L5, L7
53
+            BNE      Exit1
54
+            SHLI     L4, 8
55
+            CMPI     L5, 0
56
+            DBNE     correct1
57
+            SHLI     L6, 8
58
+            MOV      L1, L5
59
+            RET      PC, L2
60
+Exit1:      SUB      L5, L7       # Subtract chars
61
+            SARI     L5, 24
62
+            MOV      L1, L5
63
+            RET      PC, L2
64
+
65
+testzero:   CMPI     L4, 0
66
+            BE       L_5
67
+str_except:
68
+	    LDBU.N   L1, L4, 1    # Load *s1, compare bytes
69
+	    LDBU.N   L0, L5, 1    # Load *s2, compare bytes
70
+            CMP      L4, L5
71
+	    BE       testzero
72
+	    SUB      L4, L5       # Subtract chars
73
+L_5:        MOV      L1, L4
74
+	    RET      PC, L2
75
+	    .END
76
+

+ 39
- 0
src/arch/e1/include/bits/byteswap.h View File

@@ -0,0 +1,39 @@
1
+#ifndef ETHERBOOT_BITS_BYTESWAP_H
2
+#define ETHERBOOT_BITS_BYTESWAP_H
3
+
4
+/* We do not have byte swap functions ... We are
5
+ * RISC processor ...
6
+ */
7
+
8
+static inline unsigned short __swap16(volatile unsigned short v)
9
+{
10
+    return ((v << 8) | (v >> 8));
11
+}
12
+
13
+static inline unsigned int __swap32(volatile unsigned long v)
14
+{
15
+    return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
16
+}
17
+
18
+#define __bswap_constant_16(x) \
19
+	((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
20
+		(((uint16_t)(x) & 0xff00) >> 8)))
21
+
22
+#define __bswap_constant_32(x) \
23
+	((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
24
+		(((uint32_t)(x) & 0x0000ff00U) <<  8) | \
25
+		(((uint32_t)(x) & 0x00ff0000U) >>  8) | \
26
+		(((uint32_t)(x) & 0xff000000U) >> 24)))
27
+
28
+#define __bswap_16(x) \
29
+	(__builtin_constant_p(x) ? \
30
+	__bswap_constant_16(x) : \
31
+	__swap16(x))
32
+
33
+
34
+#define __bswap_32(x) \
35
+	(__builtin_constant_p(x) ? \
36
+	__bswap_constant_32(x) : \
37
+	__swap32(x))
38
+
39
+#endif /* ETHERBOOT_BITS_BYTESWAP_H */

+ 6
- 0
src/arch/e1/include/bits/cpu.h View File

@@ -0,0 +1,6 @@
1
+#ifndef E1_BITS_CPU_H
2
+#define E1_BITS_CPU_H
3
+
4
+#define cpu_setup() do {} while(0)
5
+
6
+#endif /* E1_BITS_CPU_H */

+ 6
- 0
src/arch/e1/include/bits/elf.h View File

@@ -0,0 +1,6 @@
1
+#ifndef E1_BITS_ELF_H
2
+#define E1_BITS_ELF_H
3
+
4
+/* dummy file, needed for the compilation of core/nic.c */
5
+
6
+#endif /* E1_BITS_ELF_H */

+ 6
- 0
src/arch/e1/include/bits/endian.h View File

@@ -0,0 +1,6 @@
1
+#ifndef ETHERBOOT_BITS_ENDIAN_H
2
+#define ETHERBOOT_BITS_ENDIAN_H
3
+
4
+#define __BYTE_ORDER __BIG_ENDIAN
5
+
6
+#endif /* ETHERBOOT_BITS_ENDIAN_H */

+ 35
- 0
src/arch/e1/include/bits/string.h View File

@@ -0,0 +1,35 @@
1
+#ifndef ETHERBOOT_BITS_STRING_H
2
+#define ETHERBOOT_BITS_STRING_H
3
+
4
+/* define inline optimized string functions here */
5
+
6
+#define	__HAVE_ARCH_MEMCPY
7
+//extern void * memcpy(const void *d, const void *s, size_t count);
8
+
9
+#define __HAVE_ARCH_MEMCMP
10
+//extern int memcmp(const void * s ,const void * d ,size_t );
11
+
12
+#define __HAVE_ARCH_MEMSET
13
+//extern void * memset(const void * s, int c, size_t count);
14
+
15
+#define __HAVE_ARCH_MEMMOVE
16
+static inline void *memmove(void *s1, const void *s2, size_t n) {
17
+
18
+   unsigned int i;
19
+   char *tmp = s1;
20
+   char *cs2 = (char *) s2;
21
+
22
+   if (tmp < cs2) {
23
+      for(i=0; i<n; ++i, ++tmp, ++cs2)
24
+           *tmp =  *cs2;
25
+   }
26
+   else {
27
+      tmp += n - 1;
28
+      cs2 += n - 1;
29
+      for(i=0; i<n; ++i, --tmp, --cs2)
30
+              *tmp = *cs2;
31
+   }
32
+   return(s1);
33
+}
34
+
35
+#endif /* ETHERBOOT_BITS_STRING_H */

+ 22
- 0
src/arch/e1/include/e132_xs_board.h View File

@@ -0,0 +1,22 @@
1
+#ifndef __E132_XS_BOARD_H
2
+#define __E132_XS_BOARD_H
3
+
4
+#define CONFIG_HYPERSTONE_OSC_FREQ_MHZ	15
5
+
6
+#define NR_MEMORY_REGNS	3
7
+#define BASEMEM			0x0
8
+
9
+/* SDRAM mapping */
10
+#define	SDRAM_SIZE		0x01000000
11
+#define SDRAM_BASEMEM	BASEMEM	
12
+
13
+/* SRAM mapping */
14
+#define SRAM_BASEMEM	0x40000000
15
+#define SRAM_SIZE		0x0003FFFF
16
+
17
+/* IRAM mapping */
18
+#define IRAM_BASEMEM	0xC0000000
19
+#define IRAM_SIZE		0x00003FFF
20
+
21
+
22
+#endif /* __E132_XS_BOARD_H */

+ 9
- 0
src/arch/e1/include/hooks.h View File

@@ -0,0 +1,9 @@
1
+#ifndef ETHERBOOT_E1_HOOKS_H
2
+#define ETHERBOOT_E1_HOOKS_H
3
+
4
+#define arch_main(data,params) do {} while(0)
5
+#define arch_on_exit(status) do {} while(0)
6
+#define arch_relocate_to(addr) do {} while(0)
7
+#define arch_relocated_from(old_addr) do {} while(0)
8
+
9
+#endif /* ETHERBOOT_E1_HOOKS_H */

+ 210
- 0
src/arch/e1/include/io.h View File

@@ -0,0 +1,210 @@
1
+#ifndef ETHERBOOT_IO_H
2
+#define ETHERBOOT_IO_H
3
+
4
+/* Don't require identity mapped physical memory,
5
+ * osloader.c is the only valid user at the moment.
6
+ */
7
+#if 0
8
+static inline unsigned long virt_to_phys(volatile const void *virt_addr)
9
+{
10
+	return ((unsigned long)virt_addr);
11
+}
12
+#else
13
+#define virt_to_phys(vaddr)	((unsigned long) (vaddr))
14
+#endif
15
+
16
+#if 0
17
+static inline void *phys_to_virt(unsigned long phys_addr)
18
+{
19
+	return (void *)(phys_addr);
20
+}
21
+#else
22
+#define phys_to_virt(vaddr)	((void *) (vaddr))
23
+#endif
24
+
25
+/* virt_to_bus converts an addresss inside of etherboot [_start, _end]
26
+ * into a memory address cards can use.
27
+ */
28
+#define virt_to_bus virt_to_phys
29
+
30
+/* bus_to_virt reverses virt_to_bus, the address must be output
31
+ * from virt_to_bus to be valid.  This function does not work on
32
+ * all bus addresses.
33
+ */
34
+#define bus_to_virt phys_to_virt
35
+
36
+#define iounmap(addr)				((void)0)
37
+#define ioremap(physaddr, size)			(physaddr)
38
+
39
+#define IORegAddress	13
40
+#define IOWait			11
41
+#define IOSetupTime		8
42
+#define IOAccessTime	5
43
+#define IOHoldTime		3
44
+
45
+#define SLOW_IO_ACCESS ( 0x3 << IOSetupTime | 0x0 << IOWait | 7 << IOAccessTime | 3 << IOHoldTime )
46
+
47
+/* The development board can generate up to 15 Chip selects */
48
+#define NR_CS	16
49
+
50
+extern unsigned int io_periph[NR_CS];
51
+#define ETHERNET_CS 4
52
+
53
+static inline unsigned short _swapw(volatile unsigned short v)
54
+{
55
+    return ((v << 8) | (v >> 8));
56
+}
57
+
58
+static inline unsigned int _swapl(volatile unsigned long v)
59
+{
60
+    return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
61
+}
62
+
63
+#define  hy_inpw(addr)  						\
64
+	({   register unsigned long dummy, dummy1; 			\
65
+		 dummy  = addr; 						\
66
+		 asm volatile  ("LDW.IOD   %1, %0, 0" 	\
67
+				 		: "=l" (dummy1) 		\
68
+					   	: "l" (dummy)); dummy1; })
69
+
70
+
71
+#define  hy_outpw(x, addr)						  \
72
+	({   register unsigned long dummy0,dummy1; \
73
+	 	 dummy0 = addr; 					  \
74
+		 dummy1 = x;						  \
75
+		 asm volatile  ("STW.IOD   %1, %0, 0" \
76
+						 : "=l" (dummy1) 	  \
77
+						 : "l"(dummy0), "l" (dummy1)); dummy1; })
78
+
79
+#define readb(addr)	({ unsigned char  __v = inregb(addr); __v; })
80
+#define readw(addr)	({ unsigned short __v = inregw(addr); __v; })
81
+#define readl(addr)	({ unsigned long  __v = inregl(addr); __v; })
82
+
83
+#define writeb(b,addr) (void)(outreg(b, addr))
84
+#define writew(b,addr) (void)(outreg(b, addr))
85
+#define writel(b,addr) (void)(outreg(b, addr))
86
+
87
+static inline unsigned long common_io_access(unsigned long addr)
88
+{
89
+	return io_periph[(addr & 0x03C00000) >> 22];
90
+}
91
+
92
+static inline volatile unsigned char inregb(volatile unsigned long reg)
93
+{
94
+	unsigned char val;
95
+
96
+	val = hy_inpw(common_io_access(reg) | ((0xf & reg) << IORegAddress)); 
97
+	return val;
98
+}
99
+
100
+static inline volatile unsigned short inregw(volatile unsigned long reg)
101
+{
102
+	unsigned short val;
103
+
104
+	val = hy_inpw(common_io_access(reg) | ((0xf & reg) << IORegAddress)); 
105
+	return val;
106
+}
107
+
108
+static inline volatile unsigned long inregl(volatile unsigned long reg)
109
+{
110
+	unsigned long val;
111
+
112
+	val = hy_inpw(common_io_access(reg) | ((0xf & reg) << IORegAddress)); 
113
+	return val;
114
+}
115
+
116
+static inline void outreg(volatile unsigned long val, volatile unsigned long reg)
117
+{
118
+		
119
+	hy_outpw(val, (common_io_access(reg) | ((0xf & reg) << IORegAddress)));
120
+}
121
+
122
+static inline void io_outsb(unsigned int addr, void *buf, int len)
123
+{
124
+	unsigned long tmp;
125
+	unsigned char *bp = (unsigned char *) buf;
126
+
127
+	tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
128
+
129
+	while (len--){
130
+		hy_outpw(_swapw(*bp++), tmp);
131
+	}
132
+}
133
+
134
+static inline void io_outsw(volatile unsigned int addr, void *buf, int len)
135
+{
136
+	unsigned long tmp;
137
+	unsigned short *bp = (unsigned short *) buf;
138
+	
139
+	tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
140
+
141
+	while (len--){
142
+		hy_outpw(_swapw(*bp++), tmp);
143
+	}
144
+}
145
+
146
+static inline void io_outsl(volatile unsigned int addr, void *buf, int len)
147
+{
148
+	unsigned long tmp;
149
+	unsigned int *bp = (unsigned int *) buf;
150
+		
151
+	tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
152
+
153
+	while (len--){
154
+		hy_outpw(_swapl(*bp++), tmp);
155
+	}
156
+}
157
+
158
+static inline void io_insb(volatile unsigned int addr, void *buf, int len)
159
+{
160
+	unsigned long tmp;
161
+	unsigned char *bp = (unsigned char *) buf;
162
+
163
+	tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
164
+
165
+	while (len--)
166
+		*bp++ = hy_inpw((unsigned char) tmp);
167
+	
168
+}
169
+
170
+static inline void io_insw(unsigned int addr, void *buf, int len)
171
+{
172
+	unsigned long tmp;
173
+	unsigned short *bp = (unsigned short *) buf;
174
+
175
+	tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
176
+
177
+	while (len--)
178
+		*bp++ = _swapw((unsigned short)hy_inpw(tmp));
179
+
180
+}
181
+
182
+static inline void io_insl(unsigned int addr, void *buf, int len)
183
+{
184
+	unsigned long tmp;
185
+	unsigned int *bp = (unsigned int *) buf;
186
+
187
+	tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
188
+
189
+	while (len--)
190
+		*bp++ = _swapl((unsigned int)hy_inpw(tmp));
191
+}
192
+
193
+#define inb(addr)    readb(addr)
194
+#define inw(addr)    readw(addr)
195
+#define inl(addr)    readl(addr)
196
+#define outb(x,addr) ((void) writeb(x,addr))
197
+#define outw(x,addr) ((void) writew(x,addr))
198
+#define outl(x,addr) ((void) writel(x,addr))
199
+
200
+#define insb(a,b,l) io_insb(a,b,l)
201
+#define insw(a,b,l) io_insw(a,b,l)
202
+#define insl(a,b,l) io_insl(a,b,l)
203
+#define outsb(a,b,l) io_outsb(a,b,l)
204
+#define outsw(a,b,l) io_outsw(a,b,l)
205
+#define outsl(a,b,l) io_outsl(a,b,l)
206
+	
207
+#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
208
+#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
209
+
210
+#endif /* ETHERBOOT_IO_H */

+ 12
- 0
src/arch/e1/include/latch.h View File

@@ -0,0 +1,12 @@
1
+#ifndef LATCH_H
2
+#define LATCH_H
3
+
4
+//#define TICKS_PER_SEC		(1000000UL)
5
+#define TICKS_PER_SEC		(625000UL)
6
+
7
+/* Fixed timer interval used for calibrating a more precise timer */
8
+//#define LATCHES_PER_SEC		10
9
+
10
+void sleep_latch(void);
11
+
12
+#endif /* LATCH_H */

+ 34
- 0
src/arch/e1/include/limits.h View File

@@ -0,0 +1,34 @@
1
+/*--------------------------------------------------------------------------*/
2
+/* Project:        ANSI C Standard Header Files                             */
3
+/* File:           LIMITS.H                                                 */
4
+/* Edited by:      hyperstone electronics GmbH                              */
5
+/*                 Am Seerhein 8                                            */
6
+/*                 D-78467 Konstanz, Germany                                */
7
+/* Date:           January 30, 1996                                         */
8
+/*--------------------------------------------------------------------------*/
9
+/* Purpose:                                                                 */
10
+/* The header file <limits.h> defines limits of ordinal types               */
11
+/* (char, short, int, long)                                                 */
12
+/*--------------------------------------------------------------------------*/
13
+
14
+#ifndef __LIMITS_H
15
+#define __LIMITS_H  1
16
+
17
+#define MB_LEN_MAX        1
18
+#define CHAR_BIT          8
19
+#define SCHAR_MIN         -128L
20
+#define SCHAR_MAX         127L
21
+#define UCHAR_MAX         255
22
+#define CHAR_MIN          0
23
+#define CHAR_MAX          UCHAR_MAX
24
+#define SHRT_MIN          -32768
25
+#define SHRT_MAX          32767
26
+#define USHRT_MAX         65535
27
+#define INT_MIN           0x80000000
28
+#define INT_MAX           0x7FFFFFFF
29
+#define UINT_MAX          0xFFFFFFFFL
30
+#define LONG_MIN          INT_MIN
31
+#define LONG_MAX          INT_MAX
32
+#define ULONG_MAX         UINT_MAX
33
+
34
+#endif

+ 23
- 0
src/arch/e1/include/setjmp.h View File

@@ -0,0 +1,23 @@
1
+#ifndef _SETJMP_H
2
+#define _SETJMP_H
3
+
4
+
5
+typedef struct {
6
+	unsigned long G3;
7
+	unsigned long G4;
8
+	unsigned long SavedSP;
9
+	unsigned long SavedPC;
10
+	unsigned long SavedSR;
11
+	unsigned long ReturnValue;
12
+} __jmp_buf[1];
13
+
14
+typedef struct __jmp_buf_tag	/* C++ doesn't like tagless structs.  */
15
+  {
16
+    __jmp_buf __jmpbuf;		/* Calling environment.  */
17
+    int __mask_was_saved;	/* Saved the signal mask?  */
18
+  } jmp_buf[1];
19
+
20
+void longjmp(jmp_buf state, int value );
21
+int setjmp( jmp_buf state);
22
+
23
+#endif

+ 16
- 0
src/arch/e1/include/stdint.h View File

@@ -0,0 +1,16 @@
1
+#ifndef STDINT_H
2
+#define STDINT_H
3
+
4
+typedef unsigned long      size_t;
5
+
6
+typedef unsigned char      uint8_t;
7
+typedef unsigned short     uint16_t;
8
+typedef unsigned long      uint32_t;
9
+typedef unsigned long long uint64_t;
10
+
11
+typedef signed char        int8_t;
12
+typedef signed short       int16_t;
13
+typedef signed int         int32_t;
14
+typedef signed long long   int64_t;
15
+
16
+#endif /* STDINT_H */

+ 131
- 0
src/arch/i386/Config View File

@@ -0,0 +1,131 @@
1
+# Config for i386 Etherboot
2
+#
3
+# Do not delete the tag OptionDescription and /OptionDescription
4
+# It is used to automatically generate the documentation.
5
+#
6
+# @OptionDescrition@
7
+#
8
+#	BIOS interface options:
9
+#
10
+#	-DPCBIOS
11
+#			Compile in support for the normal pcbios
12
+#	-DLINUXBIOS
13
+#			Compile in support for LinuxBIOS
14
+#	-DBBS_BUT_NOT_PNP_COMPLIANT
15
+#			Some BIOSes claim to be PNP but they don't conform
16
+#			to the BBS spec which specifies that ES:DI must
17
+#			point to the string $PnP on entry. This option
18
+#			works around those. This option must be added to
19
+#			LCONFIG.
20
+#	-DNO_DELAYED_INT
21
+#			Take control as soon as BIOS detects the ROM.
22
+#			Normally hooks onto INT18H or INT19H. Use only if you
23
+#			have a very non-conformant BIOS as it bypasses
24
+#			BIOS initialisation of devices. This only works for
25
+#			legacy ROMs, i.e. PCI_PNP_HEADER not defined.
26
+#			This option was formerly called NOINT19H.
27
+#	-DBOOT_INT18H
28
+#			Etherboot normally hooks onto INT19H for legacy ROMs.
29
+#			You can choose to hook onto INT18H (BASIC interpreter
30
+#			entry point) instead. This entry point is used when
31
+#			all boot devices have been exhausted. This option must
32
+#			be added to LCONFIG.
33
+#	-DCONFIG_PCI_DIRECT
34
+#			Define this for PCI BIOSes that do not implement
35
+#			BIOS32 or not correctly. Normally not needed.
36
+#			Only works for BIOSes of a certain era.
37
+#	-DCONFIG_TSC_CURRTICKS
38
+#			Uses the processor time stamp counter instead of reading
39
+#			the BIOS time counter.  This allows Etherboot to work
40
+#			even without a BIOS.  This only works on late model
41
+#			486s and above.
42
+#	-DCONFIG_NO_TIMER2
43
+#			Some systems do not have timer2 implemented.
44
+#			If you have a RTC this will allow you to roughly calibrate
45
+#			it using outb instructions.
46
+#	-DIBM_L40
47
+#			This option uses the 0x92 method of controlling
48
+#			A20 instead of the traditional method of using the
49
+#			keyboard controller. An explanation of A20 is here:
50
+#			http://www.win.tue.nl/~aeb/linux/kbd/A20.html
51
+#			This occurs on MCA, EISA and some embedded boards,
52
+#			and sometimes with the Fast Gate A20 option on some
53
+#			BIOSes.
54
+#			Enable this only if you are sure of what you are doing.
55
+#
56
+#	Extended cpu options
57
+
58
+#	-DCONFIG_X86_64	
59
+#			Compile in support for booting x86_64 64bit binaries.
60
+#
61
+#	PXE loader options:
62
+#
63
+#	-DPXELOADER_KEEP_ALL
64
+#			Prevent PXE loader (prefix) from unloading the
65
+#			PXE stack.  You will want to use this if, for
66
+#			example, you are booting via PXE-on-floppy.
67
+#			You may want to use it under certain
68
+#			circumstances when using the Etherboot UNDI
69
+#			driver; these are complex and best practice is
70
+#			not yet established.
71
+#			
72
+#	Obscure options you probably don't need to touch:
73
+#
74
+#	-DIGNORE_E820_MAP
75
+#			Ignore the memory map returned by the E820 BIOS
76
+#			call.  May be necessary on some buggy BIOSes.
77
+#	-DT503_AUI
78
+#			Use AUI by default on 3c503 cards.
79
+#	-DFLATTEN_REAL_MODE
80
+# 			Use 4GB segment limits when calling out to or
81
+#			returning to real-mode code.  This is necessary to
82
+#			work around some buggy code (e.g. OpenBSD's pxeboot)
83
+#			that uses flat real-mode without being sufficiently
84
+#			paranoid about the volatility of its segment limits.
85
+
86
+#
87
+# @/OptionDescription@
88
+
89
+# BIOS select don't change unless you know what you are doing
90
+CFLAGS+=	-DPCBIOS
91
+
92
+# Compile in k8/hammer support
93
+# CFLAGS+=	-DCONFIG_X86_64
94
+
95
+# Options to make a version of Etherboot that will work under linuxBIOS.
96
+# CFLAGS+=	-DLINUXBIOS -DCONFIG_TSC_CURRTICKS  -DCONSOLE_SERIAL -DCOMCONSOLE=0x3f8 -DCOMPRESERVE -DCONFIG_PCI_DIRECT -DELF_IMAGE 
97
+
98
+# These options affect the loader that is prepended to the Etherboot image
99
+# LCONFIG+=	-DBBS_BUT_NOT_PNP_COMPLIANT
100
+# LCONFIG+=	-DBOOT_INT18H
101
+
102
+# Produce code that will work inside the Bochs emulator.  The pnic
103
+# driver is probably the best one to try.
104
+# CFLAGS+=	-DCONFIG_PCI_DIRECT
105
+
106
+# Produce code that will work with OpenBSD's pxeboot
107
+# CFLAGS+=	-DFLATTEN_REAL_MODE
108
+
109
+CFLAGS+= -fstrength-reduce -fomit-frame-pointer -march=i386
110
+# Squeeze the code in as little space as possible.
111
+# gcc3 needs a different syntax to gcc2 if you want to avoid spurious warnings.
112
+GCC_VERSION	 = $(subst ., ,$(shell $(CC) -dumpversion))
113
+GCC_MAJORVERSION = $(firstword $(GCC_VERSION))
114
+ifeq ($(GCC_MAJORVERSION),2)
115
+CFLAGS+=	-malign-jumps=1 -malign-loops=1 -malign-functions=1
116
+else
117
+CFLAGS+=	-falign-jumps=1 -falign-loops=1 -falign-functions=1
118
+endif
119
+GCC_MINORVERSION = $(word 2, $(GCC_VERSION))
120
+ifneq ($(GCC_MINORVERSION),4)
121
+CFLAGS+=	-mcpu=i386
122
+endif
123
+
124
+LDFLAGS+=	-N
125
+
126
+ifeq "$(shell uname -s)" "FreeBSD"
127
+CFLAGS+=	-DIMAGE_FREEBSD -DELF_IMAGE -DAOUT_IMAGE
128
+endif
129
+
130
+# An alternate location for isolinux.bin can be set here
131
+# ISOLINUX_BIN=/path/to/isolinux.bin

+ 373
- 0
src/arch/i386/Makefile View File

@@ -0,0 +1,373 @@
1
+ARCH_FORMAT=	elf32-i386
2
+
3
+# For debugging, don't delete intermediates
4
+#.SECONDARY:
5
+
6
+LDSCRIPT=	arch/i386/core/etherboot.lds
7
+PLDSCRIPT=	arch/i386/core/etherboot.prefix.lds
8
+
9
+LCONFIG+=	-Ui386
10
+
11
+ROMLIMIT=	524288
12
+CHECKSIZE=	{ read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\
13
+	{ $(RM) $@; echo "ERROR: code size exceeds limit!"; exit 1; }; exit 0; }
14
+
15
+START=	$(BIN)/start32.o $(BIN)/linuxbios.o \
16
+	$(BIN)/bios.o $(BIN)/console.o $(BIN)/memsizes.o $(BIN)/basemem.o \
17
+	$(BIN)/hidemem.o $(BIN)/e820mangler.o \
18
+	$(BIN)/realmode.o $(BIN)/realmode_asm.o \
19
+	$(BIN)/callbacks.o $(BIN)/pxe_callbacks.o
20
+
21
+SRCS+=	arch/i386/prefix/floppyprefix.S
22
+SRCS+=	arch/i386/prefix/unhuf.S
23
+SRCS+=	arch/i386/prefix/unnrv2b.S
24
+SRCS+=	arch/i386/firmware/pcbios/bios.c
25
+SRCS+=	arch/i386/firmware/pcbios/console.c
26
+SRCS+=	arch/i386/firmware/pcbios/memsizes.c
27
+SRCS+=	arch/i386/firmware/pcbios/basemem.c
28
+SRCS+=	arch/i386/firmware/pcbios/hidemem.c
29
+SRCS+=	arch/i386/firmware/pcbios/e820mangler.S
30
+SRCS+=	arch/i386/prefix/liloprefix.S
31
+SRCS+=	arch/i386/prefix/elfprefix.S
32
+SRCS+=	arch/i386/prefix/lmelf_prefix.S
33
+SRCS+=	arch/i386/prefix/elf_dprefix.S
34
+SRCS+=	arch/i386/prefix/lmelf_dprefix.S
35
+SRCS+=	arch/i386/prefix/comprefix.S
36
+SRCS+=	arch/i386/prefix/exeprefix.S
37
+SRCS+=	arch/i386/prefix/pxeprefix.S
38
+SRCS+=	arch/i386/prefix/romprefix.S
39
+
40
+SRCS+=	arch/i386/core/init.S
41
+SRCS+=	arch/i386/core/start32.S
42
+SRCS+=	arch/i386/core/pci_io.c
43
+SRCS+=	arch/i386/core/i386_timer.c
44
+SRCS+=	arch/i386/core/elf.c
45
+SRCS+=	arch/i386/core/cpu.c
46
+SRCS+=	arch/i386/core/video_subr.c
47
+SRCS+=	arch/i386/core/pic8259.c
48
+SRCS+=	arch/i386/core/hooks.c
49
+SRCS+=	arch/i386/core/callbacks.c
50
+SRCS+=	arch/i386/core/realmode.c
51
+SRCS+=	arch/i386/core/realmode_asm.S
52
+SRCS+=	arch/i386/core/pxe_callbacks.c
53
+
54
+# ROM loaders: ISA and PCI versions
55
+ISAPREFIX=	$(BIN)/isaprefix.o
56
+ISAENTRY=	$(BIN)/isaprefix.entry.o
57
+ISAEXIT=	$(BIN)/isaprefix.exit.o
58
+PCIPREFIX=	$(BIN)/pciprefix.o
59
+PCIENTRY=	$(BIN)/pciprefix.entry.o
60
+PCIEXIT=	$(BIN)/pciprefix.exit.o
61
+# Variables xxx_ROMTYPE are defined by genrules.pl.  ROMENTRY and
62
+# ROMEXIT will evaluate to give the correct objects to use.
63
+TARGETBASE=$(patsubst $(BIN)/%,%,$(firstword $(subst ., ,$@)))
64
+ROMCARD=$(firstword $(subst --, ,$(TARGETBASE)))
65
+ROMTYPE=$(firstword $(ROMTYPE_$(ROMCARD)) ISA)
66
+romENTRY=$($(ROMTYPE)ENTRY)
67
+romEXIT=$($(ROMTYPE)EXIT)
68
+
69
+# Target type for generic prf rules
70
+TARGETTYPE=$(patsubst .%,%, $(suffix $(basename $@)))
71
+TARGETENTRY=$($(TARGETTYPE)ENTRY)
72
+TARGETEXIT=$($(TARGETTYPE)EXIT)
73
+
74
+# Other real-mode entry loaders
75
+dskPREFIX=	$(BIN)/floppyprefix.o
76
+dskENTRY=	$(BIN)/floppyprefix.entry.o
77
+dskEXIT=	$(BIN)/floppyprefix.exit.o
78
+comPREFIX=	$(BIN)/comprefix.o
79
+comENTRY=	$(BIN)/comprefix.entry.o
80
+comEXIT=	$(BIN)/comprefix.exit.o
81
+exePREFIX=	$(BIN)/exeprefix.o
82
+exeENTRY=	$(BIN)/exeprefix.entry.o
83
+exeEXIT=	$(BIN)/exeprefix.exit.o
84
+liloPREFIX=	$(BIN)/liloprefix.o
85
+liloENTRY=	$(BIN)/liloprefix.entry.o
86
+liloEXIT=	$(BIN)/liloprefix.exit.o
87
+bImagePREFIX=	$(BIN)/bImageprefix.o
88
+bImageENTRY=	$(BIN)/bImageprefix.entry.o
89
+bImageEXIT=	$(BIN)/bImageprefix.exit.o
90
+pxePREFIX=	$(BIN)/pxeprefix.o
91
+pxeENTRY=	$(BIN)/pxeprefix.entry.o
92
+pxeEXIT=	$(BIN)/pxeprefix.exit.o
93
+rawPREFIX=	$(BIN)/nullprefix.o
94
+rawENTRY=	$(BIN)/nullprefix.entry.o
95
+rawEXIT=	$(BIN)/nullprefix.exit.o
96
+
97
+# Protected mode entry loaders
98
+elfPREFIX=	$(BIN)/elfprefix.o
99
+elfENTRY=	$(BIN)/elfprefix.entry.o
100
+elfEXIT=	$(BIN)/elfprefix.exit.o
101
+lmelfPREFIX=	$(BIN)/lmelf_prefix.o
102
+lmelfENTRY=	$(BIN)/lmelf_prefix.entry.o
103
+lmelfEXIT=	$(BIN)/lmelf_prefix.exit.o
104
+elfdPREFIX=	$(BIN)/elf_dprefix.o
105
+elfdENTRY=	$(BIN)/elf_dprefix.entry.o
106
+elfdEXIT=	$(BIN)/elf_dprefix.exit.o
107
+lmelfdPREFIX=	$(BIN)/lmelf_dprefix.o
108
+lmelfdENTRY=	$(BIN)/lmelf_dprefix.entry.o
109
+lmelfdEXIT=	$(BIN)/lmelf_dprefix.exit.o
110
+
111
+include		$(BIN)/Roms
112
+
113
+all:		$(ROMS)
114
+allroms:	$(ROMS)
115
+allzroms:	$(ROMS)
116
+alldsks:	$(EB_DSKS)
117
+allzdsks:	$(EB_ZDSKS)
118
+alllilos:	$(EB_LILOS)
119
+allzlilos:	$(EB_ZLILOS)
120
+allbImages:	$(EB_BIMAGES)
121
+allbzImages:	$(EB_BZIMAGES)
122
+allpxes:	$(EB_PXES)
123
+allzpxes:	$(EB_ZPXES)
124
+allelfs:	$(EB_ELFS)
125
+allzelfs:	$(EB_ZELFS)
126
+alllmelfs:	$(EB_LMELFS)
127
+allzlmelfs:	$(EB_ZLMELFS)
128
+allelfds:	$(EB_ELFDS)
129
+allzelfds:	$(EB_ZELFDS)
130
+alllmelfds:	$(EB_LMELFDS)
131
+allzlmelfds:	$(EB_ZLMELFDS)
132
+allcoms:	$(EB_COMS)
133
+allexes:	$(EB_EXES)
134
+allisos:	$(EB_ISOS)
135
+alllisos:	$(EB_LISOS)
136
+
137
+BOBJS+=		$(BIN)/pci_io.o $(BIN)/i386_timer.o
138
+BOBJS+=		$(BIN)/elf.o $(BIN)/cpu.o $(BIN)/video_subr.o
139
+BOBJS+=		$(BIN)/pic8259.o $(BIN)/hooks.o
140
+
141
+# ROM loaders
142
+
143
+$(ISAPREFIX):	arch/i386/prefix/romprefix.S $(MAKEDEPS)
144
+	$(CPP) $(CFLAGS) $(LCONFIG) -Ui386 -D ASSEMBLY $< \
145
+		| $(AS) $(ASFLAGS) -o $@ 
146
+
147
+$(PCIPREFIX):	arch/i386/prefix/romprefix.S $(MAKEDEPS)
148
+	$(CPP) -DPCI_PNP_HEADER $(CFLAGS) $(LCONFIG) -Ui386 -D ASSEMBLY $< \
149
+		| $(AS) $(ASFLAGS) -o $@ 
150
+
151
+# Prefix splitters
152
+$(BIN)/%prefix.entry.o: $(BIN)/%prefix.o $(MAKEDEPS)
153
+	$(OBJCOPY) -R .text16 $< $@
154
+
155
+$(BIN)/%prefix.exit.o: $(BIN)/%prefix.o $(MAKEDEPS)
156
+	$(OBJCOPY) -R .prefix $< $@
157
+
158
+# Generic prefix objects
159
+PREFIXOBJS = $(BIN)/init.o
160
+ZPREFIXOBJS = $(BIN)/init.o $(BIN)/unnrv2b.o
161
+
162
+# Utilities
163
+$(BIN)/nrv2b:	util/nrv2b.c
164
+	$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
165
+
166
+ZFILELEN = perl util/zfilelen.pl
167
+
168
+# Pattern Rules
169
+
170
+# General for compiling/assembly source files
171
+
172
+$(BIN)/%.o:	arch/i386/core/%.c $(MAKEDEPS)
173
+	$(CC) $(CFLAGS) -o $@ -c $<
174
+
175
+$(BIN)/%.o:	arch/i386/core/%.S $(MAKEDEPS)
176
+	$(CPP) $(CFLAGS) -Ui386 -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
177
+
178
+$(BIN)/%.o:	arch/i386/firmware/pcbios/%.c $(MAKEDEPS)
179
+	$(CC) $(CFLAGS) -o $@ -c $<
180
+
181
+$(BIN)/%.o:	arch/i386/firmware/pcbios/%.S $(MAKEDEPS)
182
+	$(CPP) $(CFLAGS) -Ui386 -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
183
+
184
+$(BIN)/%.o:	arch/i386/prefix/%.S $(MAKEDEPS)
185
+	$(CPP) $(CFLAGS) -Ui386 -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
186
+
187
+# general rule for 16bit .o, may be overridden
188
+$(BIN)/%.o:	$(BIN)/%.s
189
+	$(AS) $(ASFLAGS) -o $@ $<
190
+
191
+# general rule for .bin (plain binary loader code), may be overridden
192
+$(BIN)/%.bin:	$(BIN)/%.o
193
+	$(OBJCOPY) -O binary $< $@
194
+
195
+# general rule for .z (compressed binary code), may be overridden
196
+# rule for .z is in top level Makefile
197
+# Give the directory name, e.g. use $(BIN)/rtl8139.com as the target.
198
+
199
+$(BIN)/%.zo:	$(BIN)/%.zbin arch/i386/core/prefixzdata.lds $(MAKEDEPS)
200
+	$(LD) -T arch/i386/core/prefixzdata.lds -b binary $< -o $@
201
+
202
+$(BIN)/%.uo:	$(BIN)/%.bin arch/i386/core/prefixudata.lds $(MAKEDEPS)
203
+	$(LD) -T arch/i386/core/prefixudata.lds -b binary $< -o $@
204
+
205
+# Intermediate prf rules
206
+
207
+%.prf:  %.rt $(PREFIXOBJS) %.rt1.uo %.rt2.uo $(MAKEDEPS)
208
+	$(MAKE) $(TARGETENTRY)
209
+	$(LD) $(LDFLAGS) -T $(PLDSCRIPT) $(TARGETENTRY) -R $(subst $(MAKEDEPS),,$^)  -o $@ 
210
+
211
+%.zprf:  %.rt $(ZPREFIXOBJS) %.rt1.uo %.rt2.zo $(MAKEDEPS)
212
+	$(MAKE) $(TARGETENTRY)
213
+	$(LD) $(LDFLAGS) -T $(PLDSCRIPT) $(TARGETENTRY) -R $(subst $(MAKEDEPS),,$^)  -o $@ 
214
+
215
+# general rules for normal/compressed ROM images, may be overridden
216
+SUFFIXES +=	rom zrom
217
+
218
+$(BIN)/%.rom.rt: $(BIN)/%.rt.o  $(ISAENTRY) $(PCIENTRY) $(ISAEXIT) $(PCIEXIT) $(LDSCRIPT) $(MAKEDEPS)
219
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(romEXIT) $<
220
+	@$(SIZE) $@ | $(CHECKSIZE)
221
+
222
+$(BIN)/%.rom: $(BIN)/%.rom.prf
223
+	$(OBJCOPY) -O binary $< $@
224
+	$(MAKEROM) $(MAKEROM_FLAGS) $(MAKEROM_$(ROMCARD)) $(MAKEROM_ID_$(ROMCARD)) -i$(IDENT) $@
225
+
226
+$(BIN)/%.zrom: $(BIN)/%.rom.zprf
227
+	$(OBJCOPY) -O binary $< $@
228
+	$(MAKEROM) $(MAKEROM_FLAGS) $(MAKEROM_$(ROMCARD)) $(MAKEROM_ID_$(ROMCARD)) -i$(IDENT) $@
229
+
230
+# general rules for ELF images
231
+SUFFIXES +=	elf zelf
232
+$(BIN)/%.elf.rt:  $(BIN)/%.rt.o $(elfENTRY) $(elfEXIT) $(LDSCRIPT) $(MAKEDEPS)
233
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(elfEXIT)  $< 
234
+
235
+$(BIN)/%.elf: $(BIN)/%.elf.prf
236
+	$(OBJCOPY) -O binary $< $@
237
+
238
+$(BIN)/%.zelf: $(BIN)/%.elf.zprf 
239
+	$(OBJCOPY) -O binary $< $@
240
+
241
+# general rules for Long Mode ELF images
242
+SUFFIXES +=	lmelf zlmelf
243
+$(BIN)/%.lmelf.rt: $(BIN)/%.rt.o $(lmelfENTRY) $(lmelfEXIT) $(LDSCRIPT) $(MAKEDEPS)
244
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(lmelfEXIT) $<
245
+
246
+$(BIN)/%.lmelf: $(BIN)/%.lmelf.prf
247
+	$(OBJCOPY) -O binary $< $@
248
+
249
+$(BIN)/%.zlmelf: $(BIN)/%.lmelf.zprf
250
+	$(OBJCOPY) -O binary $< $@
251
+
252
+# general rules for ELF dynamic images
253
+SUFFIXES +=	elfd zelfd
254
+$(BIN)/%.elfd.rt: $(BIN)/%.rt.o $(elfdENTRY) $(elfdEXIT) $(LDSCRIPT) $(MAKEDEPS)
255
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(elfdEXIT) $<
256
+
257
+$(BIN)/%.elfd: $(BIN)/%.elfd.prf
258
+	$(OBJCOPY) -O binary $< $@
259
+
260
+$(BIN)/%.zelfd: $(BIN)/%.elfd.zprf
261
+	$(OBJCOPY) -O binary $< $@
262
+
263
+# general rules for Long Mode ELF dynamic images
264
+SUFFIXES +=	lmelfd zlmelfd
265
+$(BIN)/%.lmelfd.rt: $(BIN)/%.rt.o $(lmelfdENTRY) $(lmelfdEXIT) $(LDSCRIPT) $(MAKEDEPS)
266
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(lmelfdEXIT) $<
267
+
268
+$(BIN)/%.lmelfd: $(BIN)/%.lmelfd.prf
269
+	$(OBJCOPY) -O binary $< $@
270
+
271
+$(BIN)/%.zlmelfd: $(BIN)/%.lmelfd.zprf
272
+	$(OBJCOPY) -O binary $< $@
273
+
274
+# rules to generate a DOS loadable .com executable
275
+SUFFIXES +=	com
276
+$(BIN)/%.com.rt: $(BIN)/%.rt.o $(comENTRY) $(comEXIT) $(LDSCRIPT) $(MAKEDEPS)
277
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(comEXIT)
278
+
279
+$(BIN)/%.com: $(BIN)/%.com.zprf
280
+	$(OBJCOPY) -O binary $< $@
281
+
282
+# rules to generate a DOS loadable .exe executable
283
+SUFFIXES +=	exe
284
+$(BIN)/%.exe.rt: $(BIN)/%.rt.o $(exeENTRY) $(exeEXIT) $(LDSCRIPT) $(MAKEDEPS)
285
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(exeEXIT)
286
+	@$(SIZE) $@ | $(CHECKSIZE)
287
+
288
+$(BIN)/%.exe: $(BIN)/%.exe.prf
289
+	$(OBJCOPY) -O binary $< $@
290
+
291
+# rules to make a LILO loadable image
292
+SUFFIXES +=	lilo zlilo
293
+
294
+$(BIN)/%.lilo.rt: $(BIN)/%.rt.o $(liloENTRY) $(liloEXIT) $(LDSCRIPT) $(MAKEDEPS)
295
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(liloEXIT)
296
+	@$(SIZE) $@ | $(CHECKSIZE)
297
+
298
+$(BIN)/%.lilo: $(BIN)/%.lilo.prf
299
+	$(OBJCOPY) -O binary $< $@
300
+
301
+$(BIN)/%.zlilo: $(BIN)/%.lilo.zprf
302
+	$(OBJCOPY) -O binary $< $@
303
+
304
+# rules to make big linux boot protocol image
305
+SUFFIXES +=	bImage bzImage
306
+
307
+$(BIN)/%.bImage.rt: $(BIN)/%.rt.o $(bImageENTRY) $(bImageEXIT) $(LDSCRIPT) $(MAKEDEPS)
308
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(bImageEXIT)
309
+
310
+$(BIN)/%.bImage: $(BIN)/%.bImage.prf
311
+	$(OBJCOPY) -O binary $< $@
312
+
313
+$(BIN)/%.bzImage: $(BIN)/%.bImage.zprf
314
+	$(OBJCOPY) -O binary $< $@
315
+
316
+
317
+# rules to generate a PXE loadable image
318
+SUFFIXES +=	pxe zpxe
319
+
320
+$(BIN)/%.pxe.rt: $(BIN)/%.rt.o $(pxeENTRY) $(pxeEXIT) $(LDSCRIPT) $(MAKEDEPS)
321
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(pxeEXIT)
322
+	@$(SIZE) $@ | $(CHECKSIZE)
323
+
324
+$(BIN)/%.pxe: $(BIN)/%.pxe.prf
325
+	$(OBJCOPY) -O binary $< $@
326
+
327
+$(BIN)/%.zpxe: $(BIN)/%.pxe.zprf
328
+	$(OBJCOPY) -O binary $< $@
329
+
330
+# rules to generate the .dsk/.zdsk floppy images
331
+SUFFIXES +=	dsk zdsk
332
+
333
+$(BIN)/%.dsk.rt: $(BIN)/%.rt.o $(dskENTRY) $(dskEXIT) $(LDSCRIPT) $(MAKEDEPS)
334
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(dskEXIT)
335
+	@$(SIZE) $@ | $(CHECKSIZE)
336
+
337
+$(BIN)/%.dsk: $(BIN)/%.dsk.prf
338
+	$(OBJCOPY) -O binary $< $@
339
+
340
+$(BIN)/%.zdsk: $(BIN)/%.dsk.zprf
341
+	$(OBJCOPY) -O binary $< $@
342
+
343
+# rules to write the .dsk/.zdsk image onto a blank floppy
344
+SUFFIXES +=	fd0 zfd0
345
+%.fd0:	%.dsk
346
+	dd if=$< bs=512 conv=sync of=/dev/fd0
347
+	sync
348
+
349
+%.zfd0:	%.zdsk
350
+	dd if=$< bs=512 conv=sync of=/dev/fd0
351
+	sync
352
+
353
+# rules to create raw executable images
354
+SUFFIXES +=	raw zraw
355
+$(BIN)/%.raw.rt: $(BIN)/%.rt.o $(rawENTRY) $(rawEXIT) $(LDSCRIPT) $(MAKEDEPS)
356
+	$(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(rawEXIT)
357
+
358
+$(BIN)/%.raw: $(BIN)/%.raw.prf
359
+	$(OBJCOPY) -O binary $< $@
360
+
361
+$(BIN)/%.zraw: $(BIN)/%.raw.zprf
362
+	$(OBJCOPY) -O binary $< $@
363
+
364
+# rule to make a non-emulation ISO boot image
365
+SUFFIXES +=	iso
366
+%.iso:	util/geniso %.zlilo
367
+	ISOLINUX_BIN=${ISOLINUX_BIN} bash util/geniso $*.iso $*.zlilo
368
+
369
+# rule to make a floppy emulation ISO boot image
370
+SUFFIXES +=	liso
371
+%.liso:	util/genliso %.zlilo
372
+	bash util/genliso $*.liso $*.zlilo
373
+

+ 144
- 0
src/arch/i386/core/aout_loader.c View File

@@ -0,0 +1,144 @@
1
+/* a.out */
2
+struct exec {
3
+	unsigned long      a_midmag;	/* flags<<26 | mid<<16 | magic */
4
+	unsigned long      a_text;	/* text segment size */
5
+	unsigned long      a_data;	/* initialized data size */
6
+	unsigned long      a_bss;	/* uninitialized data size */
7
+	unsigned long      a_syms;	/* symbol table size */
8
+	unsigned long      a_entry;	/* entry point */
9
+	unsigned long      a_trsize;	/* text relocation size */
10
+	unsigned long      a_drsize;	/* data relocation size */
11
+};
12
+
13
+struct aout_state {
14
+	struct exec head;
15
+	unsigned long curaddr;
16
+	int segment;			/* current segment number, -1 for none */
17
+	unsigned long loc;		/* start offset of current block */
18
+	unsigned long skip;		/* padding to be skipped to current segment */
19
+	unsigned long toread;		/* remaining data to be read in the segment */
20
+};
21
+
22
+static struct aout_state astate;
23
+
24
+static sector_t aout_download(unsigned char *data, unsigned int len, int eof);
25
+static inline os_download_t aout_probe(unsigned char *data, unsigned int len)
26
+{
27
+	unsigned long start, mid, end, istart, iend;
28
+	if (len < sizeof(astate.head)) {
29
+		return 0;
30
+	}
31
+	memcpy(&astate.head, data, sizeof(astate.head));
32
+	if ((astate.head.a_midmag & 0xffff) != 0x010BL) {
33
+		return 0;
34
+	}
35
+	
36
+	printf("(a.out");
37
+	aout_freebsd_probe();
38
+	printf(")... ");
39
+	/* Check the aout image */
40
+	start  = astate.head.a_entry;
41
+	mid    = (((start + astate.head.a_text) + 4095) & ~4095) + astate.head.a_data;
42
+	end    = ((mid + 4095) & ~4095) + astate.head.a_bss;
43
+	istart = 4096;
44
+	iend   = istart + (mid - start);
45
+	if (!prep_segment(start, mid, end, istart, iend))
46
+		return dead_download;
47
+	astate.segment = -1;
48
+	astate.loc = 0;
49
+	astate.skip = 0;
50
+	astate.toread = 0;
51
+	return aout_download;
52
+}
53
+
54
+static sector_t aout_download(unsigned char *data, unsigned int len, int eof)
55
+{
56
+	unsigned int offset;	/* working offset in the current data block */
57
+
58
+	offset = 0;
59
+
60
+#ifdef AOUT_LYNX_KDI
61
+	astate.segment++;
62
+	if (astate.segment == 0) {
63
+		astate.curaddr = 0x100000;
64
+		astate.head.a_entry = astate.curaddr + 0x20;
65
+	}
66
+	memcpy(phys_to_virt(astate.curaddr), data, len);
67
+	astate.curaddr += len;
68
+	return 0;
69
+#endif
70
+
71
+	do {
72
+		if (astate.segment != -1) {
73
+			if (astate.skip) {
74
+				if (astate.skip >= len - offset) {
75
+					astate.skip -= len - offset;
76
+					break;
77
+				}
78
+				offset += astate.skip;
79
+				astate.skip = 0;
80
+			}
81
+
82
+			if (astate.toread) {
83
+				if (astate.toread >= len - offset) {
84
+					memcpy(phys_to_virt(astate.curaddr), data+offset,
85
+						len - offset);
86
+					astate.curaddr += len - offset;
87
+					astate.toread -= len - offset;
88
+					break;
89
+				}
90
+				memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread);
91
+				offset += astate.toread;
92
+				astate.toread = 0;
93
+			}
94
+		}
95
+
96
+		/* Data left, but current segment finished - look for the next
97
+		 * segment.  This is quite simple for a.out files.  */
98
+		astate.segment++;
99
+		switch (astate.segment) {
100
+		case 0:
101
+			/* read text */
102
+			astate.curaddr = astate.head.a_entry;
103
+			astate.skip = 4096;
104
+			astate.toread = astate.head.a_text;
105
+			break;
106
+		case 1:
107
+			/* read data */
108
+			/* skip and curaddr may be wrong, but I couldn't find
109
+			 * examples where this failed.  There is no reasonable
110
+			 * documentation for a.out available.  */
111
+			astate.skip = ((astate.curaddr + 4095) & ~4095) - astate.curaddr;
112
+			astate.curaddr = (astate.curaddr + 4095) & ~4095;
113
+			astate.toread = astate.head.a_data;
114
+			break;
115
+		case 2:
116
+			/* initialize bss and start kernel */
117
+			astate.curaddr = (astate.curaddr + 4095) & ~4095;
118
+			astate.skip = 0;
119
+			astate.toread = 0;
120
+			memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss);
121
+			goto aout_startkernel;
122
+		default:
123
+			break;
124
+		}
125
+	} while (offset < len);
126
+
127
+	astate.loc += len;
128
+
129
+	if (eof) {
130
+		unsigned long entry;
131
+
132
+aout_startkernel:
133
+		entry = astate.head.a_entry;
134
+		done(1);
135
+
136
+		aout_freebsd_boot();
137
+#ifdef AOUT_LYNX_KDI
138
+		xstart32(entry);
139
+#endif
140
+		printf("unexpected a.out variant\n");
141
+		longjmp(restart_etherboot, -2);
142
+	}
143
+	return 0;
144
+}

+ 107
- 0
src/arch/i386/core/callbacks.c View File

@@ -0,0 +1,107 @@
1
+/* Callout/callback interface for Etherboot
2
+ *
3
+ * This file provides the mechanisms for making calls from Etherboot
4
+ * to external programs and vice-versa.
5
+ *
6
+ * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
7
+ */
8
+
9
+#include "etherboot.h"
10
+#include "callbacks.h"
11
+#include "realmode.h"
12
+#include "segoff.h"
13
+#include <stdarg.h>
14
+
15
+/* Maximum amount of stack data that prefix may request to be passed
16
+ * to its exit routine
17
+ */
18
+#define MAX_PREFIX_STACK_DATA 16
19
+
20
+/* Prefix exit routine is defined in prefix object */
21
+extern void prefix_exit ( void );
22
+extern void prefix_exit_end ( void );
23
+
24
+/*****************************************************************************
25
+ *
26
+ * IN_CALL INTERFACE
27
+ *
28
+ *****************************************************************************
29
+ */
30
+
31
+/* in_call(): entry point for calls in to Etherboot from external code. 
32
+ *
33
+ * Parameters: some set up by assembly code _in_call(), others as
34
+ * passed from external code.
35
+ */
36
+uint32_t i386_in_call ( va_list ap, i386_pm_in_call_data_t pm_data,
37
+			uint32_t opcode ) {
38
+	uint32_t ret;
39
+	i386_rm_in_call_data_t rm_data;
40
+	in_call_data_t in_call_data = { &pm_data, NULL };
41
+	struct {
42
+		int data[MAX_PREFIX_STACK_DATA/4];
43
+	} in_stack;
44
+
45
+	/* Fill out rm_data if we were called from real mode */
46
+	if ( opcode & EB_CALL_FROM_REAL_MODE ) {
47
+		in_call_data.rm = &rm_data;
48
+		rm_data = va_arg ( ap, typeof(rm_data) );
49
+		/* Null return address indicates to use the special
50
+		 * prefix exit mechanism, and that there are
51
+		 * parameters on the stack that the prefix wants
52
+		 * handed to its exit routine.
53
+		 */
54
+		if ( rm_data.ret_addr.offset == 0 ) {
55
+			int n = va_arg ( ap, int ) / 4;
56
+			int i;
57
+			for ( i = 0; i < n; i++ ) {
58
+				in_stack.data[i] = va_arg ( ap, int );
59
+			}
60
+		}
61
+	}
62
+	
63
+	/* Hand off to main in_call() routine */
64
+	ret = in_call ( &in_call_data, opcode, ap );
65
+
66
+	/* If real-mode return address is null, it means that we
67
+	 * should exit via the prefix's exit path, which is part of
68
+	 * our image.  (This arrangement is necessary since the prefix
69
+	 * code itself may have been vapourised by the time we want to
70
+	 * return.)
71
+	 */
72
+	if ( ( opcode & EB_CALL_FROM_REAL_MODE ) &&
73
+	     ( rm_data.ret_addr.offset == 0 ) ) {
74
+		real_call ( prefix_exit, &in_stack, NULL );
75
+		/* Should never return */
76
+	}
77
+		
78
+	return ret;
79
+}
80
+
81
+#ifdef	CODE16
82
+
83
+/* install_rm_callback_interface(): install real-mode callback
84
+ * interface at specified address.
85
+ *
86
+ * Real-mode code may then call to this address (or lcall to this
87
+ * address plus RM_IN_CALL_FAR) in order to make an in_call() to
88
+ * Etherboot.
89
+ *
90
+ * Returns the size of the installed code, or 0 if the code could not
91
+ * be installed.
92
+ */
93
+int install_rm_callback_interface ( void *address, size_t available ) {
94
+	if ( available &&
95
+	     ( available < rm_callback_interface_size ) ) return 0;
96
+
97
+	/* Inform RM code where to find Etherboot */
98
+	rm_etherboot_location = virt_to_phys(_text);
99
+
100
+	/* Install callback interface */
101
+	memcpy ( address, &rm_callback_interface,
102
+		 rm_callback_interface_size );
103
+
104
+	return rm_callback_interface_size;
105
+}
106
+
107
+#endif	/* CODE16 */

+ 86
- 0
src/arch/i386/core/cpu.c View File

@@ -0,0 +1,86 @@
1
+#ifdef CONFIG_X86_64
2
+#include "stdint.h"
3
+#include "string.h"
4
+#include "bits/cpu.h"
5
+
6
+
7
+/* Standard macro to see if a specific flag is changeable */
8
+static inline int flag_is_changeable_p(uint32_t flag)
9
+{
10
+	uint32_t f1, f2;
11
+
12
+	asm("pushfl\n\t"
13
+	    "pushfl\n\t"
14
+	    "popl %0\n\t"
15
+	    "movl %0,%1\n\t"
16
+	    "xorl %2,%0\n\t"
17
+	    "pushl %0\n\t"
18
+	    "popfl\n\t"
19
+	    "pushfl\n\t"
20
+	    "popl %0\n\t"
21
+	    "popfl\n\t"
22
+	    : "=&r" (f1), "=&r" (f2)
23
+	    : "ir" (flag));
24
+
25
+	return ((f1^f2) & flag) != 0;
26
+}
27
+
28
+
29
+/* Probe for the CPUID instruction */
30
+static inline int have_cpuid_p(void)
31
+{
32
+	return flag_is_changeable_p(X86_EFLAGS_ID);
33
+}
34
+
35
+static void identify_cpu(struct cpuinfo_x86 *c)
36
+{
37
+	unsigned xlvl;
38
+
39
+	c->cpuid_level = -1;		/* CPUID not detected */
40
+	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
41
+	c->x86_vendor_id[0] = '\0';	/* Unset */
42
+	memset(&c->x86_capability, 0, sizeof c->x86_capability);
43
+	
44
+	if (!have_cpuid_p()) {
45
+		/* CPU doesn'thave CPUID */
46
+
47
+		/* If there are any capabilities, they'r vendor-specific */
48
+		/* enable_cpuid() would have set c->x86 for us. */
49
+	}
50
+	else {
51
+		/* CPU does have CPUID */
52
+
53
+		/* Get vendor name */
54
+		cpuid(0x00000000, &c->cpuid_level,
55
+		      (int *)&c->x86_vendor_id[0],
56
+		      (int *)&c->x86_vendor_id[8],
57
+		      (int *)&c->x86_vendor_id[4]);
58
+		
59
+		/* Initialize the standard set of capabilities */
60
+		/* Note that the vendor-specific code below might override */
61
+
62
+		/* Intel-defined flags: level 0x00000001 */
63
+		if ( c->cpuid_level >= 0x00000001 ) {
64
+			unsigned tfms, junk;
65
+			cpuid(0x00000001, &tfms, &junk, &junk,
66
+			      &c->x86_capability[0]);
67
+			c->x86 = (tfms >> 8) & 15;
68
+			c->x86_model = (tfms >> 4) & 15;
69
+			c->x86_mask = tfms & 15;
70
+		}
71
+
72
+		/* AMD-defined flags: level 0x80000001 */
73
+		xlvl = cpuid_eax(0x80000000);
74
+		if ( (xlvl & 0xffff0000) == 0x80000000 ) {
75
+			if ( xlvl >= 0x80000001 )
76
+				c->x86_capability[1] = cpuid_edx(0x80000001);
77
+		}
78
+	}
79
+}
80
+
81
+struct cpuinfo_x86 cpu_info;
82
+void cpu_setup(void)
83
+{
84
+	identify_cpu(&cpu_info);
85
+}
86
+#endif /* CONFIG_X86_64 */

+ 135
- 0
src/arch/i386/core/elf.c View File

@@ -0,0 +1,135 @@
1
+#include "etherboot.h"
2
+#include "elf.h"
3
+
4
+
5
+#define NAME "Etherboot"
6
+
7
+#if defined(PCBIOS)
8
+#define FIRMWARE "PCBIOS"
9
+#endif
10
+#if defined(LINUXBIOS)
11
+#define FIRMWARE "LinuxBIOS"
12
+#endif
13
+#if !defined(FIRMWARE)
14
+#error "No BIOS selected"
15
+#endif
16
+
17
+#define SZ(X) ((sizeof(X)+3) & ~3)
18
+#define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))
19
+
20
+struct elf_notes {
21
+	/* The note header */
22
+	struct Elf_Bhdr hdr;
23
+
24
+	/* First the Fixed sized entries that must be well aligned */
25
+
26
+	/* Pointer to bootp data */
27
+	Elf_Nhdr nf1;
28
+	char     nf1_name[SZ(EB_PARAM_NOTE)];
29
+	uint32_t nf1_bootp_data;
30
+
31
+	/* Pointer to ELF header */
32
+	Elf_Nhdr nf2;
33
+	char     nf2_name[SZ(EB_PARAM_NOTE)];
34
+	uint32_t nf2_header;
35
+
36
+	/* A copy of the i386 memory map */
37
+	Elf_Nhdr nf3;
38
+	char     nf3_name[SZ(EB_PARAM_NOTE)];
39
+	struct meminfo nf3_meminfo;
40
+
41
+	/* Then the variable sized data string data where alignment does not matter */
42
+
43
+	/* The bootloader name */
44
+	Elf_Nhdr nv1;
45
+	char     nv1_desc[SZ(NAME)];
46
+	/* The bootloader version */
47
+	Elf_Nhdr nv2;
48
+	char     nv2_desc[SZ(VERSION)];
49
+	/* The firmware type */
50
+	Elf_Nhdr nv3;
51
+	char     nv3_desc[SZ(FIRMWARE)];
52
+	/* Name of the loaded image */
53
+	Elf_Nhdr nv4;
54
+	char     nv4_loaded_image[128];
55
+	/* An empty command line */
56
+	Elf_Nhdr nv5;
57
+	char     nv5_cmdline[SZ("")];
58
+};
59
+
60
+#define ELF_NOTE_COUNT  (3 + 5)
61
+
62
+static struct elf_notes notes;
63
+struct Elf_Bhdr *prepare_boot_params(void *header)
64
+{
65
+	memset(&notes, 0, sizeof(notes));
66
+	notes.hdr.b_signature = ELF_BHDR_MAGIC;
67
+	notes.hdr.b_size      = sizeof(notes);
68
+	notes.hdr.b_checksum  = 0;
69
+	notes.hdr.b_records   = ELF_NOTE_COUNT;
70
+
71
+	/* Initialize the fixed length entries. */
72
+	notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE);
73
+	notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data);
74
+	notes.nf1.n_type   = EB_BOOTP_DATA;
75
+	CP(notes.nf1_name,   EB_PARAM_NOTE);
76
+	notes.nf1_bootp_data = virt_to_phys(BOOTP_DATA_ADDR);
77
+
78
+	notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE);
79
+	notes.nf2.n_descsz = sizeof(notes.nf2_header);
80
+	notes.nf2.n_type   = EB_HEADER;
81
+	CP(notes.nf2_name,   EB_PARAM_NOTE);
82
+	notes.nf2_header   = virt_to_phys(header);
83
+
84
+	notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE);
85
+	notes.nf3.n_descsz = sizeof(notes.nf3_meminfo);
86
+	notes.nf3.n_type   = EB_I386_MEMMAP;
87
+	CP(notes.nf3_name,   EB_PARAM_NOTE);
88
+	memcpy(&notes.nf3_meminfo, &meminfo, sizeof(meminfo));
89
+
90
+	/* Initialize the variable length entries */
91
+	notes.nv1.n_namesz = 0;
92
+	notes.nv1.n_descsz = sizeof(NAME);
93
+	notes.nv1.n_type   = EBN_BOOTLOADER_NAME;
94
+	CP(notes.nv1_desc,   NAME);
95
+
96
+	notes.nv2.n_namesz = 0;
97
+	notes.nv2.n_descsz = sizeof(VERSION);
98
+	notes.nv2.n_type   = EBN_BOOTLOADER_VERSION;
99
+	CP(notes.nv2_desc,   VERSION);
100
+
101
+	notes.nv3.n_namesz = 0;
102
+	notes.nv3.n_descsz = sizeof(FIRMWARE);
103
+	notes.nv3.n_type   = EBN_FIRMWARE_TYPE;
104
+	CP(notes.nv3_desc,   FIRMWARE);
105
+
106
+	/* Attempt to pass the name of the loaded image */
107
+	notes.nv4.n_namesz = 0;
108
+	notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image);
109
+	notes.nv4.n_type   = EBN_LOADED_IMAGE;
110
+	memcpy(&notes.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image));
111
+
112
+	/* Pass an empty command line for now */
113
+	notes.nv5.n_namesz = 0;
114
+	notes.nv5.n_descsz = sizeof("");
115
+	notes.nv5.n_type   = EBN_COMMAND_LINE;
116
+	CP(notes.nv5_cmdline,   "");
117
+
118
+
119
+	notes.hdr.b_checksum = ipchksum(&notes, sizeof(notes));
120
+	/* Like UDP invert a 0 checksum to show that a checksum is present */
121
+	if (notes.hdr.b_checksum == 0) {
122
+		notes.hdr.b_checksum = 0xffff;
123
+	}
124
+	return &notes.hdr;
125
+}
126
+
127
+int elf_start(unsigned long machine __unused_i386, unsigned long entry, unsigned long params)
128
+{
129
+#if defined(CONFIG_X86_64)
130
+	if (machine == EM_X86_64) {
131
+		return xstart_lm(entry, params);
132
+	}
133
+#endif
134
+	return xstart32(entry, params);
135
+}

+ 90
- 0
src/arch/i386/core/etherboot.lds View File

@@ -0,0 +1,90 @@
1
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2
+OUTPUT_ARCH(i386)
3
+
4
+ENTRY(_text)
5
+SECTIONS {
6
+	. = ALIGN(16);
7
+	/* Start address of Etherboot in the virtual address space */
8
+	_virt_start = 0;
9
+	_text = . ;
10
+	.text.nocompress : {
11
+		*(.text*.nocompress)
12
+		. = ALIGN(16);
13
+	} = 0x9090
14
+
15
+	.text16 : {
16
+		_text16 = .;
17
+		*(.text16)
18
+		*(.text16.*)
19
+		_etext16 = . ;
20
+	}
21
+	.text.compress : {
22
+		*(.text)
23
+		*(.text.*)
24
+	} = 0x9090
25
+	.rodata : {
26
+		. = ALIGN(4);
27
+		*(.rodata)
28
+		*(.rodata.*)
29
+	}
30
+	. = ALIGN(4);
31
+	.drivers.pci : {
32
+		pci_drivers = . ;
33
+		*(.drivers.pci);
34
+		pci_drivers_end = . ;
35
+	}
36
+	. = ALIGN(4);
37
+	.drivers.isa : {
38
+		isa_drivers = . ;
39
+		*(.drivers.isa);
40
+		isa_drivers_end = .;
41
+	}
42
+	_etext = . ;
43
+	_data = . ;
44
+	.data : {
45
+		*(.data)
46
+		*(.data.*)
47
+	}
48
+	_edata = . ;
49
+	_uncompressed_verbatim_end = . ;
50
+	. = ALIGN(16);
51
+	.bss.preserve : {
52
+		*(.bss.preserve)
53
+		*(.bss.preserve.*)
54
+	}
55
+	_bss = . ;
56
+	.bss : {
57
+		*(.bss)
58
+		*(.bss.*)
59
+	}
60
+	. = ALIGN(16);
61
+	_ebss = .;
62
+	_stack = . ;
63
+	.stack : {
64
+		_stack_start = . ;
65
+		*(.stack)
66
+		*(.stack.*)
67
+		_stack_end = . ;
68
+	}
69
+	_bss_size = _ebss - _bss;
70
+	_stack_offset = _stack - _text ;
71
+	_stack_offset_pgh = _stack_offset / 16 ;
72
+	_stack_size = _stack_end - _stack_start ;
73
+	. = ALIGN(16);
74
+	_end = . ;
75
+
76
+	/DISCARD/ : {
77
+		*(.comment)
78
+		*(.note)
79
+	}
80
+
81
+	/* PXE-specific symbol calculations.  The results of these are
82
+	 * needed in romprefix.S, which is why they must be calculated
83
+	 * here.
84
+	 */
85
+	_pxe_stack_size = _pxe_stack_t_size
86
+		+ _pxe_callback_interface_size
87
+		+ _rm_callback_interface_size
88
+		+ _e820mangler_size + 15 ;
89
+
90
+}

+ 100
- 0
src/arch/i386/core/etherboot.prefix.lds View File

@@ -0,0 +1,100 @@
1
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2
+OUTPUT_ARCH(i386)
3
+
4
+ENTRY(_prefix_start)
5
+SECTIONS {
6
+	/* Prefix */
7
+	.prefix : {
8
+		_verbatim_start = . ;
9
+		_prefix_start = . ;
10
+		*(.prefix)
11
+		. = ALIGN(16);
12
+		_prefix_end = . ;
13
+	} = 0x9090
14
+	_prefix_size = _prefix_end - _prefix_start;
15
+
16
+	.text.nocompress : {
17
+		*(.prefix.udata)
18
+	} = 0x9090
19
+
20
+	decompress_to = . ;
21
+	.prefix.zdata : {
22
+		_compressed = . ;
23
+		*(.prefix.zdata)
24
+		_compressed_end = . ;
25
+	}
26
+	_compressed_size = _compressed_end - _compressed;
27
+
28
+	. = ALIGN(16);
29
+	_verbatim_end = . ;
30
+
31
+
32
+	/* Size of the core of etherboot in memory */
33
+	_base_size = _end - _text;
34
+
35
+	/* _prefix_size is the length of the non-core etherboot prefix */
36
+	_prefix_size = _prefix_end - _prefix_start;
37
+
38
+	/* _verbatim_size is the actual amount that has to be copied to base memory */
39
+	_verbatim_size = _verbatim_end - _verbatim_start;
40
+
41
+	/* _image_size is the amount of base memory needed to run */
42
+	_image_size = _base_size +  _prefix_size;
43
+
44
+	/* Standard sizes rounded up to paragraphs */
45
+	_prefix_size_pgh   = (_prefix_size + 15) / 16;
46
+	_verbatim_size_pgh = (_verbatim_size + 15) / 16;
47
+	_image_size_pgh    = (_image_size + 15) / 16 ;
48
+	
49
+	/* Standard sizes in sectors */
50
+	_prefix_size_sct   = (_prefix_size + 511) / 512;
51
+	_verbatim_size_sct = (_verbatim_size + 511) / 512;
52
+	_image_size_sct    = (_image_size + 511) / 512;
53
+
54
+	/* Symbol offsets and sizes for the exe prefix */
55
+	_exe_hdr_size   = 32;
56
+	_exe_size       = _verbatim_size; /* Should this be - 32 to exclude the header? */
57
+	_exe_size_tail  = (_exe_size) % 512;
58
+	_exe_size_pages = ((_exe_size) + 511) / 512;
59
+	_exe_bss_size   = ((_image_size - _verbatim_size) + 15) / 16;
60
+	_exe_ss_offset  = (_stack_offset + _prefix_size - _exe_hdr_size + 15) / 16 ;
61
+
62
+	/* This is where we copy the compressed image before decompression.
63
+	 * Prepare to decompress in place.  The end mark is about 8.25 bytes long,
64
+	 * and the worst case symbol is about 16.5 bytes long.  Therefore
65
+	 * We need to reserve at least 25 bytes of slack here.  
66
+	 * Currently I reserve 2048 bytes of just slack to be safe :)
67
+	 * 2048 bytes easily falls within the BSS (the defualt stack is 4096 bytes)
68
+	 * so we really are decompressing in place.
69
+	 * 
70
+	 * Hmm. I missed a trick.  In the very worst case (no compression)
71
+	 * the encoded data is 9/8 the size as it started out so to be completely
72
+	 * safe I need to be 1/8 of the uncompressed code size past the end.
73
+	 * This will still fit compfortably into our bss in any conceivable scenario.
74
+	 */
75
+	_compressed_copy = _edata + _prefix_size  - _compressed_size +
76
+		/* The amount to overflow _edata */
77
+		MAX( ((_edata - _text + 7) / 8) , 2016 ) + 32; 
78
+	_assert = ASSERT( ( _compressed_copy - _prefix_size ) < _ebss , "Cannot decompress in place" ) ; 
79
+
80
+	decompress = DEFINED(decompress) ? decompress : 0;
81
+	/DISCARD/ : {
82
+		*(.comment)
83
+		*(.note)
84
+	}
85
+
86
+	/* Symbols used by the prefixes whose addresses are inconvinient 
87
+	 * to compute, at runtime in the code.
88
+	 */
89
+	image_basemem_size = DEFINED(image_basemem_size)? image_basemem_size : 65536;
90
+	image_basemem      = DEFINED(image_basemem)?     image_basemem : 65536;
91
+	_prefix_real_to_prot          = _real_to_prot         + _prefix_size ;
92
+	_prefix_prot_to_real          = _prot_to_real         + _prefix_size ;
93
+	_prefix_image_basemem_size    = image_basemem_size    + _prefix_size ;
94
+	_prefix_image_basemem         = image_basemem         + _prefix_size ;
95
+	_prefix_rm_in_call            = _rm_in_call           + _prefix_size ;
96
+	_prefix_in_call               = _in_call              + _prefix_size ;
97
+	_prefix_rom                   = rom                   + _prefix_size ;
98
+	_prefix_rm_etherboot_location = rm_etherboot_location + _prefix_size ;
99
+	_prefix_stack_end             = _stack_end            + _prefix_size ;
100
+}

+ 377
- 0
src/arch/i386/core/freebsd_loader.c View File

@@ -0,0 +1,377 @@
1
+/* bootinfo */
2
+#define BOOTINFO_VERSION 1
3
+#define NODEV           (-1)    /* non-existent device */
4
+#define PAGE_SHIFT      12              /* LOG2(PAGE_SIZE) */
5
+#define PAGE_SIZE       (1<<PAGE_SHIFT) /* bytes/page */
6
+#define PAGE_MASK       (PAGE_SIZE-1)
7
+#define N_BIOS_GEOM     8
8
+
9
+struct bootinfo {
10
+        unsigned int            bi_version;
11
+        const unsigned char     *bi_kernelname;
12
+        struct nfs_diskless     *bi_nfs_diskless;
13
+                                /* End of fields that are always present. */
14
+#define bi_endcommon            bi_n_bios_used
15
+        unsigned int            bi_n_bios_used;
16
+        unsigned long           bi_bios_geom[N_BIOS_GEOM];
17
+        unsigned int            bi_size;
18
+        unsigned char           bi_memsizes_valid;
19
+        unsigned char           bi_pad[3];
20
+        unsigned long           bi_basemem;
21
+        unsigned long           bi_extmem;
22
+        unsigned long           bi_symtab;
23
+        unsigned long           bi_esymtab;
24
+	/* Note that these are in the FreeBSD headers but were not here... */
25
+	unsigned long           bi_kernend;		/* end of kernel space */
26
+	unsigned long           bi_envp;		/* environment */
27
+	unsigned long           bi_modulep;		/* preloaded modules */
28
+};
29
+
30
+static struct bootinfo bsdinfo;
31
+
32
+#ifdef ELF_IMAGE
33
+static Elf32_Shdr *shdr;	/* To support the FreeBSD kludge! */
34
+static Address symtab_load;
35
+static Address symstr_load;
36
+static int symtabindex;
37
+static int symstrindex;
38
+#endif
39
+
40
+static enum {
41
+	Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,
42
+} image_type = Unknown;
43
+
44
+static unsigned int off;
45
+
46
+
47
+#ifdef ELF_IMAGE
48
+static void elf_freebsd_probe(void)
49
+{
50
+	image_type = Elf;
51
+	if (	(estate.e.elf32.e_entry & 0xf0000000) && 
52
+		(estate.e.elf32.e_type == ET_EXEC))
53
+	{
54
+		image_type = Elf_FreeBSD;
55
+		printf("/FreeBSD");
56
+		off = -(estate.e.elf32.e_entry & 0xff000000);
57
+		estate.e.elf32.e_entry += off;
58
+	}
59
+	/* Make sure we have a null to start with... */
60
+	shdr = 0;
61
+	
62
+	/* Clear the symbol index values... */
63
+	symtabindex = -1;
64
+	symstrindex = -1;
65
+	
66
+	/* ...and the load addresses of the symbols  */
67
+	symtab_load = 0;
68
+	symstr_load = 0;
69
+}
70
+
71
+static void elf_freebsd_fixup_segment(void)
72
+{
73
+	if (image_type == Elf_FreeBSD) {
74
+		estate.p.phdr32[estate.segment].p_paddr += off;
75
+	}
76
+}
77
+
78
+static void elf_freebsd_find_segment_end(void)
79
+{
80
+	/* Count the bytes read even for the last block
81
+	 * as we will need to know where the last block
82
+	 * ends in order to load the symbols correctly.
83
+	 * (plus it could be useful elsewhere...)
84
+	 * Note that we need to count the actual size,
85
+	 * not just the end of the disk image size.
86
+	 */
87
+	estate.curaddr += 
88
+		(estate.p.phdr32[estate.segment].p_memsz - 
89
+		estate.p.phdr32[estate.segment].p_filesz);
90
+}
91
+
92
+static int elf_freebsd_debug_loader(unsigned int offset)
93
+{
94
+	/* No more segments to be loaded - time to start the
95
+	 * nasty state machine to support the loading of
96
+	 * FreeBSD debug symbols due to the fact that FreeBSD
97
+	 * uses/exports the kernel's debug symbols in order
98
+	 * to make much of the system work!  Amazing (arg!)
99
+	 *
100
+	 * We depend on the fact that for the FreeBSD kernel,
101
+	 * there is only one section of debug symbols and that
102
+	 * the section is after all of the loaded sections in
103
+	 * the file.  This assumes a lot but is somewhat required
104
+	 * to make this code not be too annoying.  (Where do you
105
+	 * load symbols when the code has not loaded yet?)
106
+	 * Since this function is actually just a callback from
107
+	 * the network data transfer code, we need to be able to
108
+	 * work with the data as it comes in.  There is no chance
109
+	 * for doing a seek other than forwards.
110
+	 *
111
+	 * The process we use is to first load the section
112
+	 * headers.  Once they are loaded (shdr != 0) we then
113
+	 * look for where the symbol table and symbol table
114
+	 * strings are and setup some state that we found
115
+	 * them and fall into processing the first one (which
116
+	 * is the symbol table) and after that has been loaded,
117
+	 * we try the symbol strings.  Note that the order is
118
+	 * actually required as the memory image depends on
119
+	 * the symbol strings being loaded starting at the
120
+	 * end of the symbol table.  The kernel assumes this
121
+	 * layout of the image.
122
+	 *
123
+	 * At any point, if we get to the end of the load file
124
+	 * or the section requested is earlier in the file than
125
+	 * the current file pointer, we just end up falling
126
+	 * out of this and booting the kernel without this
127
+	 * information.
128
+	 */
129
+
130
+	/* Make sure that the next address is long aligned... */
131
+	/* Assumes size of long is a power of 2... */
132
+	estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1);
133
+	
134
+	/* If we have not yet gotten the shdr loaded, try that */
135
+	if (shdr == 0)
136
+	{
137
+		estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;
138
+		estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);
139
+		if (estate.toread)
140
+		{
141
+#if ELF_DEBUG
142
+			printf("shdr *, size %lX, curaddr %lX\n", 
143
+				estate.toread, estate.curaddr);
144
+#endif
145
+			
146
+			/* Start reading at the curaddr and make that the shdr */
147
+			shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);
148
+			
149
+			/* Start to read... */
150
+			return 1;
151
+		}
152
+	}
153
+	else
154
+	{
155
+		/* We have the shdr loaded, check if we have found
156
+		 * the indexs where the symbols are supposed to be */
157
+		if ((symtabindex == -1) && (symstrindex == -1))
158
+		{
159
+			int i;
160
+			/* Make sure that the address is page aligned... */
161
+			/* Symbols need to start in their own page(s)... */
162
+			estate.curaddr = (estate.curaddr + 4095) & ~4095;
163
+			
164
+			/* Need to make new indexes... */
165
+			for (i=0; i < estate.e.elf32.e_shnum; i++)
166
+			{
167
+				if (shdr[i].sh_type == SHT_SYMTAB)
168
+				{
169
+					int j;
170
+					for (j=0; j < estate.e.elf32.e_phnum; j++)
171
+					{
172
+						/* Check only for loaded sections */
173
+						if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80))
174
+						{
175
+							/* Only the extra symbols */
176
+							if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) &&
177
+								((shdr[i].sh_offset + shdr[i].sh_size) <=
178
+									(estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz)))
179
+							{
180
+								shdr[i].sh_offset=0;
181
+								shdr[i].sh_size=0;
182
+								break;
183
+							}
184
+						}
185
+					}
186
+					if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))
187
+					{
188
+						symtabindex = i;
189
+						symstrindex = shdr[i].sh_link;
190
+					}
191
+				}
192
+			}
193
+		}
194
+		
195
+		/* Check if we have a symbol table index and have not loaded it */
196
+		if ((symtab_load == 0) && (symtabindex >= 0))
197
+		{
198
+			/* No symbol table yet?  Load it first... */
199
+			
200
+			/* This happens to work out in a strange way.
201
+			 * If we are past the point in the file already,
202
+			 * we will skip a *large* number of bytes which
203
+			 * ends up bringing us to the end of the file and
204
+			 * an old (default) boot.  Less code and lets
205
+			 * the state machine work in a cleaner way but this
206
+			 * is a nasty side-effect trick... */
207
+			estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset);
208
+			
209
+			/* And we need to read this many bytes... */
210
+			estate.toread = shdr[symtabindex].sh_size;
211
+			
212
+			if (estate.toread)
213
+			{
214
+#if ELF_DEBUG
215
+				printf("db sym, size %lX, curaddr %lX\n", 
216
+					estate.toread, estate.curaddr);
217
+#endif
218
+				/* Save where we are loading this... */
219
+				symtab_load = phys_to_virt(estate.curaddr);
220
+				
221
+				*((long *)phys_to_virt(estate.curaddr)) = estate.toread;
222
+				estate.curaddr += sizeof(long);
223
+				
224
+				/* Start to read... */
225
+				return 1;
226
+			}
227
+		}
228
+		else if ((symstr_load == 0) && (symstrindex >= 0))
229
+		{
230
+			/* We have already loaded the symbol table, so
231
+			 * now on to the symbol strings... */
232
+			
233
+			
234
+			/* Same nasty trick as above... */
235
+			estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);
236
+			
237
+			/* And we need to read this many bytes... */
238
+			estate.toread = shdr[symstrindex].sh_size;
239
+			
240
+			if (estate.toread)
241
+			{
242
+#if ELF_DEBUG
243
+				printf("db str, size %lX, curaddr %lX\n", 
244
+					estate.toread, estate.curaddr);
245
+#endif
246
+				/* Save where we are loading this... */
247
+				symstr_load = phys_to_virt(estate.curaddr);
248
+				
249
+				*((long *)phys_to_virt(estate.curaddr)) = estate.toread;
250
+				estate.curaddr += sizeof(long);
251
+				
252
+				/* Start to read... */
253
+				return 1;
254
+			}
255
+		}
256
+	}
257
+	/* all done */
258
+	return 0;
259
+}
260
+
261
+static void elf_freebsd_boot(unsigned long entry) 
262
+{
263
+	if (image_type != Elf_FreeBSD)
264
+		return;
265
+
266
+	memset(&bsdinfo, 0, sizeof(bsdinfo));
267
+	bsdinfo.bi_basemem = meminfo.basememsize;
268
+	bsdinfo.bi_extmem = meminfo.memsize;
269
+	bsdinfo.bi_memsizes_valid = 1;
270
+	bsdinfo.bi_version = BOOTINFO_VERSION;
271
+	bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
272
+	bsdinfo.bi_nfs_diskless = NULL;
273
+	bsdinfo.bi_size = sizeof(bsdinfo);
274
+#define RB_BOOTINFO     0x80000000      /* have `struct bootinfo *' arg */  
275
+	if(freebsd_kernel_env[0] != '\0'){
276
+		freebsd_howto |= RB_BOOTINFO;
277
+		bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env;
278
+	}
279
+	
280
+	/* Check if we have symbols loaded, and if so,
281
+	 * made the meta_data needed to pass those to
282
+	 * the kernel. */
283
+	if ((symtab_load !=0) && (symstr_load != 0))
284
+	{
285
+		unsigned long *t;
286
+		
287
+		bsdinfo.bi_symtab = symtab_load;
288
+		
289
+		/* End of symbols (long aligned...) */
290
+		/* Assumes size of long is a power of 2... */
291
+		bsdinfo.bi_esymtab = (symstr_load +
292
+			sizeof(long) +
293
+			*((long *)symstr_load) +
294
+			sizeof(long) - 1) & ~(sizeof(long) - 1);
295
+		
296
+		/* Where we will build the meta data... */
297
+		t = phys_to_virt(bsdinfo.bi_esymtab);
298
+		
299
+#if ELF_DEBUG
300
+		printf("Metadata at %lX\n",t);
301
+#endif
302
+		
303
+		/* Set up the pointer to the memory... */
304
+		bsdinfo.bi_modulep = virt_to_phys(t);
305
+		
306
+		/* The metadata structure is an array of 32-bit
307
+		 * words where we store some information about the
308
+		 * system.  This is critical, as FreeBSD now looks
309
+		 * only for the metadata for the extended symbol
310
+		 * information rather than in the bootinfo.
311
+		 */
312
+		/* First, do the kernel name and the kernel type */
313
+		/* Note that this assumed x86 byte order... */
314
+		
315
+		/* 'kernel\0\0' */
316
+		*t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;
317
+		
318
+		/* 'elf kernel\0\0' */
319
+		*t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;
320
+		
321
+		/* Now the symbol start/end - note that they are
322
+		 * here in local/physical address - the Kernel
323
+		 * boot process will relocate the addresses. */
324
+		*t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab;
325
+		*t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab;
326
+		
327
+		*t++=MODINFO_END; *t++=0; /* end of metadata */
328
+		
329
+		/* Since we have symbols we need to make
330
+		 * sure that the kernel knows its own end
331
+		 * of memory...  It is not _end but after
332
+		 * the symbols and the metadata... */
333
+		bsdinfo.bi_kernend = virt_to_phys(t);
334
+		
335
+		/* Signal locore.s that we have a valid bootinfo
336
+		 * structure that was completely filled in. */
337
+		freebsd_howto |= 0x80000000;
338
+	}
339
+	
340
+	xstart32(entry, freebsd_howto, NODEV, 0, 0, 0, 
341
+		virt_to_phys(&bsdinfo), 0, 0, 0);
342
+	longjmp(restart_etherboot, -2);
343
+}
344
+#endif
345
+
346
+#ifdef AOUT_IMAGE
347
+static void aout_freebsd_probe(void)
348
+{
349
+	image_type = Aout;
350
+	if (((astate.head.a_midmag >> 16) & 0xffff) == 0) {
351
+		/* Some other a.out variants have a different
352
+		 * value, and use other alignments (e.g. 1K),
353
+		 * not the 4K used by FreeBSD.  */
354
+		image_type = Aout_FreeBSD;
355
+		printf("/FreeBSD");
356
+		off = -(astate.head.a_entry & 0xff000000);
357
+		astate.head.a_entry += off;
358
+	}
359
+}
360
+
361
+static void aout_freebsd_boot(void)
362
+{
363
+	if (image_type == Aout_FreeBSD) {
364
+		memset(&bsdinfo, 0, sizeof(bsdinfo));
365
+		bsdinfo.bi_basemem = meminfo.basememsize;
366
+		bsdinfo.bi_extmem = meminfo.memsize;
367
+		bsdinfo.bi_memsizes_valid = 1;
368
+		bsdinfo.bi_version = BOOTINFO_VERSION;
369
+		bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
370
+		bsdinfo.bi_nfs_diskless = NULL;
371
+		bsdinfo.bi_size = sizeof(bsdinfo);
372
+		xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0, 
373
+			virt_to_phys(&bsdinfo), 0, 0, 0);
374
+		longjmp(restart_etherboot, -2);
375
+	}
376
+}
377
+#endif

+ 35
- 0
src/arch/i386/core/hooks.c View File

@@ -0,0 +1,35 @@
1
+#include "etherboot.h"
2
+#include "callbacks.h"
3
+#include <stdarg.h>
4
+
5
+void arch_main ( in_call_data_t *data __unused, va_list params __unused )
6
+{
7
+#ifdef PCBIOS
8
+	/* Deallocate base memory used for the prefix, if applicable
9
+	 */
10
+	forget_prefix_base_memory();
11
+#endif
12
+
13
+}
14
+
15
+void arch_relocated_from (unsigned long old_addr )
16
+{
17
+
18
+#ifdef PCBIOS
19
+	/* Deallocate base memory used for the Etherboot runtime,
20
+	 * if applicable
21
+	 */
22
+	forget_runtime_base_memory( old_addr );
23
+#endif
24
+
25
+}
26
+
27
+void arch_on_exit ( int exit_status __unused ) 
28
+{
29
+#ifdef PCBIOS
30
+	/* Deallocate the real-mode stack now.  We will reallocate
31
+	 * the stack if are going to use it after this point.
32
+	 */
33
+	forget_real_mode_stack();
34
+#endif
35
+}

+ 191
- 0
src/arch/i386/core/i386_timer.c View File

@@ -0,0 +1,191 @@
1
+/* A couple of routines to implement a low-overhead timer for drivers */
2
+
3
+ /*
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2, or (at
7
+ * your option) any later version.
8
+ */
9
+
10
+#include	"etherboot.h"
11
+#include	"timer.h"
12
+#include	"latch.h"
13
+
14
+void __load_timer2(unsigned int ticks)
15
+{
16
+	/*
17
+	 * Now let's take care of PPC channel 2
18
+	 *
19
+	 * Set the Gate high, program PPC channel 2 for mode 0,
20
+	 * (interrupt on terminal count mode), binary count,
21
+	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
22
+	 *
23
+	 * Note some implementations have a bug where the high bits byte
24
+	 * of channel 2 is ignored.
25
+	 */
26
+	/* Set up the timer gate, turn off the speaker */
27
+	/* Set the Gate high, disable speaker */
28
+	outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
29
+	/* binary, mode 0, LSB/MSB, Ch 2 */
30
+	outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
31
+	/* LSB of ticks */
32
+	outb(ticks & 0xFF, TIMER2_PORT);
33
+	/* MSB of ticks */
34
+	outb(ticks >> 8, TIMER2_PORT);
35
+}
36
+
37
+static int __timer2_running(void)
38
+{
39
+	return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
40
+}
41
+
42
+#if !defined(CONFIG_TSC_CURRTICKS)
43
+void setup_timers(void)
44
+{
45
+	return;
46
+}
47
+
48
+void load_timer2(unsigned int ticks)
49
+{
50
+	return __load_timer2(ticks);
51
+}
52
+
53
+int timer2_running(void)
54
+{
55
+	return __timer2_running();
56
+}
57
+
58
+void ndelay(unsigned int nsecs)
59
+{
60
+	waiton_timer2((nsecs * CLOCK_TICK_RATE)/1000000000);
61
+}
62
+void udelay(unsigned int usecs)
63
+{
64
+	waiton_timer2((usecs * TICKS_PER_MS)/1000);
65
+}
66
+#endif /* !defined(CONFIG_TSC_CURRTICKS) */
67
+
68
+#if defined(CONFIG_TSC_CURRTICKS)
69
+
70
+#define rdtsc(low,high) \
71
+     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
72
+
73
+#define rdtscll(val) \
74
+     __asm__ __volatile__ ("rdtsc" : "=A" (val))
75
+
76
+
77
+/* Number of clock ticks to time with the rtc */
78
+#define LATCH 0xFF
79
+
80
+#define LATCHES_PER_SEC ((CLOCK_TICK_RATE + (LATCH/2))/LATCH)
81
+#define TICKS_PER_LATCH ((LATCHES_PER_SEC + (TICKS_PER_SEC/2))/TICKS_PER_SEC)
82
+
83
+static void sleep_latch(void)
84
+{
85
+	__load_timer2(LATCH);
86
+	while(__timer2_running());
87
+}
88
+
89
+/* ------ Calibrate the TSC ------- 
90
+ * Time how long it takes to excute a loop that runs in known time.
91
+ * And find the convertion needed to get to CLOCK_TICK_RATE
92
+ */
93
+
94
+
95
+static unsigned long long calibrate_tsc(void)
96
+{
97
+	unsigned long startlow, starthigh;
98
+	unsigned long endlow, endhigh;
99
+	
100
+	rdtsc(startlow,starthigh);
101
+	sleep_latch();
102
+	rdtsc(endlow,endhigh);
103
+
104
+	/* 64-bit subtract - gcc just messes up with long longs */
105
+	__asm__("subl %2,%0\n\t"
106
+		"sbbl %3,%1"
107
+		:"=a" (endlow), "=d" (endhigh)
108
+		:"g" (startlow), "g" (starthigh),
109
+		"0" (endlow), "1" (endhigh));
110
+	
111
+	/* Error: ECPUTOOFAST */
112
+	if (endhigh)
113
+		goto bad_ctc;
114
+	
115
+	endlow *= TICKS_PER_LATCH;
116
+	return endlow;
117
+
118
+	/*
119
+	 * The CTC wasn't reliable: we got a hit on the very first read,
120
+	 * or the CPU was so fast/slow that the quotient wouldn't fit in
121
+	 * 32 bits..
122
+	 */
123
+bad_ctc:
124
+	printf("bad_ctc\n");
125
+	return 0;
126
+}
127
+
128
+static unsigned long clocks_per_tick;
129
+void setup_timers(void)
130
+{
131
+	if (!clocks_per_tick) {
132
+		clocks_per_tick = calibrate_tsc();
133
+		/* Display the CPU Mhz to easily test if the calibration was bad */
134
+		printf("CPU %ld Mhz\n", (clocks_per_tick/1000 * TICKS_PER_SEC)/1000);
135
+	}
136
+}
137
+
138
+unsigned long currticks(void)
139
+{
140
+	unsigned long clocks_high, clocks_low;
141
+	unsigned long currticks;
142
+	/* Read the Time Stamp Counter */
143
+	rdtsc(clocks_low, clocks_high);
144
+
145
+	/* currticks = clocks / clocks_per_tick; */
146
+	__asm__("divl %1"
147
+		:"=a" (currticks)
148
+		:"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
149
+
150
+
151
+	return currticks;
152
+}
153
+
154
+static unsigned long long timer_timeout;
155
+static int __timer_running(void)
156
+{
157
+	unsigned long long now;
158
+	rdtscll(now);
159
+	return now < timer_timeout;
160
+}
161
+
162
+void udelay(unsigned int usecs)
163
+{
164
+	unsigned long long now;
165
+	rdtscll(now);
166
+	timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
167
+	while(__timer_running());
168
+}
169
+void ndelay(unsigned int nsecs)
170
+{
171
+	unsigned long long now;
172
+	rdtscll(now);
173
+	timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
174
+	while(__timer_running());
175
+}
176
+
177
+void load_timer2(unsigned int timer2_ticks)
178
+{
179
+	unsigned long long now;
180
+	unsigned long clocks;
181
+	rdtscll(now);
182
+	clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
183
+	timer_timeout = now + clocks;
184
+}
185
+
186
+int timer2_running(void)
187
+{
188
+	return __timer_running();
189
+}
190
+
191
+#endif /* RTC_CURRTICKS */

+ 305
- 0
src/arch/i386/core/init.S View File

@@ -0,0 +1,305 @@
1
+#include "callbacks.h"
2
+	.equ CR0_PE, 1
3
+	
4
+	.text
5
+	.arch i386
6
+	.section ".prefix", "ax", @progbits
7
+
8
+#undef CODE16
9
+#if defined(PCBIOS)
10
+#define	CODE16
11
+#endif
12
+
13
+/* We have two entry points: "conventional" (at the start of the file)
14
+ * and "callback" (at _entry, 2 bytes in).  The "callback" entry
15
+ * should be used if the caller wishes to provide a specific opcode.
16
+ * It is equivalent to a call to in_call.  Using the "conventional"
17
+ * entry point is equivalent to using the "callback" entry point with
18
+ * an opcode of EB_OPCODE_MAIN.
19
+ *
20
+ * Both entry points can be called in either 16-bit real or 32-bit
21
+ * protected mode with flat physical addresses.  We detect which mode
22
+ * the processor is in and call either in_call or rm_in_call as
23
+ * appropriate.  Note that the mode detection code must therefore be
24
+ * capable of doing the same thing in either mode, even though the
25
+ * machine code instructions will be interpreted differently.
26
+ *
27
+ * The decompressor will be invoked if necessary to decompress
28
+ * Etherboot before attempting to jump to it.
29
+ */
30
+
31
+/******************************************************************************
32
+ * Entry points and mode detection code
33
+ ******************************************************************************
34
+ */
35
+
36
+	.code32
37
+/* "Conventional" entry point: caller provides no opcode */
38
+	.globl	_start
39
+_start:
40
+	/* Set flag to indicate conventional entry point used */
41
+	pushl	$0			/* "pushw $0" in 16-bit code */
42
+	/* Fall through to "callback" entry point */
43
+	
44
+/* "Callback" entry point */
45
+	.globl	_entry
46
+_entry:
47
+	
48
+#ifdef CODE16
49
+	/* CPU mode detection code */
50
+	pushl	%eax			/* "pushw %ax" in 16-bit code */
51
+	pushw	%ax			/* "pushl %eax" in 16-bit code */
52
+	movl	%cr0, %eax		/* Test protected mode bit */
53
+	testb	$CR0_PE, %al
54
+	popw	%ax			/* "popl %eax" in 16-bit code */
55
+	popl	%eax			/* "popw %eax" in 16-bit code */
56
+	jz	rmode
57
+#endif /* CODE16 */
58
+
59
+/******************************************************************************
60
+ * Entered in protected mode
61
+ ******************************************************************************
62
+ */
63
+		
64
+	.code32
65
+pmode:
66
+	cmpl	$0, 0(%esp)		/* Conventional entry point used? */
67
+	jne	1f
68
+	/* Entered via conventional entry point: set up stack */
69
+	xchgl	%eax, 4(%esp)		/* %eax = return addr, store %eax */
70
+	movl	%eax, 0(%esp)		/* 0(%esp) = return address */
71
+	movl	$(EB_OPCODE_MAIN|EB_USE_INTERNAL_STACK|EB_SKIP_OPCODE), %eax
72
+	xchgl	%eax, 4(%esp)		/* 4(%esp) = opcode, restore %eax */
73
+1:
74
+	/* Run decompressor if necessary */
75
+	pushl	%eax
76
+	movl	$decompress, %eax
77
+	testl	%eax, %eax
78
+	jz	1f
79
+	call	decompress
80
+1:	popl	%eax
81
+
82
+	/* Make in_call to Etherboot */
83
+	jmp	_prefix_in_call
84
+
85
+/******************************************************************************
86
+ * Entered in real mode
87
+ ******************************************************************************
88
+ */
89
+	
90
+#ifdef CODE16
91
+	.code16
92
+rmode:
93
+	pushw	%ax			/* Padding */
94
+	pushw	%bp
95
+	movw	%sp, %bp
96
+	cmpw	$0, 6(%bp)		/* Conventional entry point used? */
97
+	jne	1f
98
+	/* Entered via conventional entry point: set up stack */
99
+	pushw	%ax
100
+	movw	6(%bp), %ax
101
+	movw	%ax, 2(%bp)		/* Move return address down */
102
+	movl	$(EB_OPCODE_MAIN|EB_USE_INTERNAL_STACK|EB_SKIP_OPCODE), 4(%bp)
103
+	popw	%ax
104
+	popw	%bp
105
+	jmp	2f
106
+1:	/* Entered via callback entry point: do nothing */
107
+	popw	%bp
108
+	popw	%ax
109
+2:
110
+	/* Preserve registers */
111
+	pushw	%ds
112
+	pushl	%eax
113
+	
114
+	/* Run decompressor if necessary.  Decompressor is 32-bit
115
+	 * code, so we must switch to pmode first.  Save and restore
116
+	 * GDT over transition to pmode.
117
+	 */
118
+	movl	$decompress, %eax
119
+	testl	%eax, %eax
120
+	jz	1f
121
+	pushw	%ds
122
+	pushw	%es
123
+	pushw	%fs
124
+	pushw	%gs
125
+	subw	$8, %sp
126
+	pushw	%bp
127
+	movw	%sp, %bp
128
+	sgdt	2(%bp)
129
+	pushw	%ss			/* Store params for _prot_to_real */
130
+	pushw	%cs
131
+	call	_prefix_real_to_prot
132
+	.code32
133
+	call	decompress
134
+	call	_prefix_prot_to_real
135
+	.code16
136
+	popw	%ax			/* skip */
137
+	popw	%ax			/* skip */
138
+	lgdt	2(%bp)
139
+	popw	%bp
140
+	addw	$8, %sp
141
+	popw	%gs
142
+	popw	%fs
143
+	popw	%es
144
+	popw	%ds
145
+1:
146
+
147
+	/* Set rm_etherboot_location */
148
+	xorl	%eax, %eax
149
+	movw	%cs, %ax
150
+	movw	%ax, %ds
151
+	shll	$4, %eax
152
+	addl	$_prefix_size, %eax
153
+	movl	%eax, _prefix_rm_etherboot_location
154
+
155
+	/* Restore registers */
156
+	popl	%eax
157
+	popw	%ds
158
+
159
+	/* Make real-mode in_call to Etherboot */
160
+	jmp	_prefix_rm_in_call
161
+#endif /* CODE16 */
162
+
163
+/******************************************************************************
164
+ * Utility routines that can be called by the "prefix".
165
+ ******************************************************************************
166
+ */
167
+
168
+#ifdef CODE16
169
+
170
+/* Prelocate code: either to an area at the top of free base memory.
171
+ * Switch stacks to use the stack within the resulting
172
+ * Etherboot image.
173
+ *
174
+ * On entry, %cs:0000 must be the start of the prefix: this is used to
175
+ * locate the code to be copied.
176
+ *
177
+ * This routine takes a single word parameter: the number of bytes to
178
+ * be transferred from the old stack to the new stack (excluding the
179
+ * return address and this parameter itself, which will always be
180
+ * copied).  If this value is negative, the stacks will not be
181
+ * switched.
182
+ *
183
+ * Control will "return" to the appropriate point in the relocated
184
+ * image.
185
+ */
186
+
187
+#define PRELOC_PRESERVE ( 20 )
188
+#define PRELOC_OFFSET_RETADDR ( PRELOC_PRESERVE )
189
+#define PRELOC_OFFSET_RETADDR_E ( PRELOC_OFFSET_RETADDR + 4 )
190
+#define PRELOC_OFFSET_COPY ( PRELOC_OFFSET_RETADDR_E )
191
+#define PRELOC_OFFSET_COPY_E ( PRELOC_OFFSET_COPY + 2 )
192
+
193
+#define PRELOC_ALWAYS_COPY ( PRELOC_OFFSET_COPY_E )
194
+	
195
+	.code16
196
+	.globl	prelocate
197
+prelocate:
198
+	/* Pad to allow for expansion of return address */
199
+	pushw	%ax
200
+	
201
+	/* Preserve registers */
202
+	pushaw
203
+	pushw	%ds
204
+	pushw	%es
205
+	
206
+	/* Claim an area of base memory from the BIOS and put the
207
+	 * payload there.
208
+	 */
209
+	movw	$0x40, %bx
210
+	movw	%bx, %es
211
+	movw	%es:(0x13), %bx		/* FBMS in kb to %ax */
212
+	shlw	$6, %bx			/* ... in paragraphs */
213
+	subw	$_image_size_pgh, %bx	/* Subtract space for image */
214
+	shrw	$6, %bx			/* Round down to nearest kb */
215
+	movw	%bx, %es:(0x13)		/* ...and claim memory from BIOS */
216
+	shlw	$6, %bx
217
+
218
+	/* At this point %bx contains the segment address for the
219
+	 * start of the image (image = prefix + runtime).
220
+	 */
221
+
222
+	/* Switch stacks */
223
+	movw	%ss, %ax
224
+	movw	%ax, %ds
225
+	movw	%sp, %si		/* %ds:si = current %ss:sp */
226
+	movw	%ss:PRELOC_OFFSET_COPY(%si), %cx
227
+	testw	%cx, %cx
228
+	js	1f
229
+	leaw	_stack_offset_pgh(%bx), %ax /* %ax = new %ss */
230
+	movw	%ax, %es
231
+	movw	$_stack_size, %di
232
+	addw	$PRELOC_ALWAYS_COPY, %cx
233
+	subw	%cx, %di		/* %es:di = new %ss:sp */
234
+	movw	%ax, %ss		/* Set new %ss:sp */
235
+	movw	%di, %sp
236
+	cld
237
+	rep movsb			/* Copy stack contents */
238
+1:	
239
+
240
+	/* Do the image copy backwards, since if there's overlap with
241
+	 * a forward copy then it means we're going to get trashed
242
+	 * during the copy anyway...
243
+	 */
244
+	pushal				/* Preserve 32-bit registers */
245
+	movw	%bx, %es		/* Destination base for copy */
246
+	pushw	%cs
247
+	popw	%ds			/* Source base for copy */
248
+	movl	$_verbatim_size-1, %ecx	/* Offset to last byte */
249
+	movl	%ecx, %esi
250
+	movl	%ecx, %edi
251
+	incl	%ecx			/* Length */
252
+	std				/* Backwards copy of binary */
253
+	ADDR32 rep movsb
254
+	cld
255
+	popal				/* Restore 32-bit registers */
256
+
257
+	/* Store (%bx<<4) as image_basemem to be picked up by
258
+	 * basemem.c.  Also store image_size, since there's no other
259
+	 * way that we can later know how much memory we allocated.
260
+	 * (_zfile_size is unavailable when rt2 is linked).
261
+	 */
262
+	pushl	%eax
263
+	xorl	%eax, %eax
264
+	movw	%bx, %ax
265
+	shll	$4, %eax
266
+	movl	%eax, %es:_prefix_image_basemem
267
+	movl	$_image_size, %es:_prefix_image_basemem_size
268
+	popl	%eax
269
+
270
+	/* Expand original near return address into far return to new
271
+	 * code location.
272
+	 */
273
+	movw	%sp, %bp
274
+	xchgw	%bx, (PRELOC_OFFSET_RETADDR+2)(%bp)
275
+	movw	%bx, (PRELOC_OFFSET_RETADDR+0)(%bp)
276
+
277
+	/* Restore registers and return */
278
+	popw	%es
279
+	popw	%ds
280
+	popaw
281
+	lret				/* Jump to relocated code */
282
+
283
+	/* Utility routine to free base memory allocated by prelocate.
284
+	 * Ensure that said memory is not in use (e.g. for the CPU
285
+	 * stack) before calling this routine.
286
+	 */
287
+	.globl deprelocate
288
+deprelocate:	
289
+	/* Claim an area of base memory from the BIOS and put the
290
+	 * payload there.
291
+	 */
292
+	pushw	%ax
293
+	pushw	%es
294
+	movw	$0x40, %ax
295
+	movw	%ax, %es
296
+	movw	%es:(0x13), %ax		/* FBMS in kb to %ax */
297
+	shlw	$6, %ax			/* ... in paragraphs */
298
+	addw	$_image_size_pgh+0x40-1, %ax /* Add space for image and... */
299
+	shrw	$6, %ax			/* ...round up to nearest kb */
300
+	movw	%ax, %es:(0x13)		/* Give memory back to BIOS */
301
+	popw	%es
302
+	popw	%ax
303
+	ret
304
+	
305
+#endif /* CODE16 */

+ 143
- 0
src/arch/i386/core/multiboot_loader.c View File

@@ -0,0 +1,143 @@
1
+/* Multiboot support
2
+ *
3
+ * 2003-07-02 mmap fix and header probe by SONE Takeshi
4
+ */
5
+
6
+struct multiboot_mods {
7
+	unsigned mod_start;
8
+	unsigned mod_end;
9
+	unsigned char *string;
10
+	unsigned reserved;
11
+};
12
+
13
+struct multiboot_mmap {
14
+	unsigned int size;
15
+	unsigned int base_addr_low;
16
+	unsigned int base_addr_high;
17
+	unsigned int length_low;
18
+	unsigned int length_high;
19
+	unsigned int type;
20
+};
21
+
22
+/* The structure of a Multiboot 0.6 parameter block.  */
23
+struct multiboot_info {
24
+	unsigned int flags;
25
+#define MULTIBOOT_MEM_VALID       0x01
26
+#define MULTIBOOT_BOOT_DEV_VALID  0x02
27
+#define MULTIBOOT_CMDLINE_VALID   0x04
28
+#define MULTIBOOT_MODS_VALID      0x08
29
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
30
+#define MULTIBOOT_ELF_SYMS_VALID  0x20
31
+#define MULTIBOOT_MMAP_VALID      0x40
32
+	unsigned int memlower;
33
+	unsigned int memupper;
34
+	unsigned int bootdev;
35
+	unsigned int cmdline;	/* physical address of the command line */
36
+	unsigned mods_count;
37
+	struct multiboot_mods *mods_addr;
38
+	unsigned syms_num;
39
+	unsigned syms_size;
40
+	unsigned syms_addr;
41
+	unsigned syms_shndx;
42
+	unsigned mmap_length;
43
+	unsigned  mmap_addr;
44
+	/* The structure actually ends here, so I might as well put
45
+	 * the ugly e820 parameters here...
46
+	 */
47
+	struct multiboot_mmap mmap[E820MAX];
48
+};
49
+
50
+/* Multiboot image header (minimal part) */
51
+struct multiboot_header {
52
+	unsigned int magic;
53
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
54
+	unsigned int flags;
55
+	unsigned int checksum;
56
+};
57
+
58
+static struct multiboot_header *mbheader;
59
+
60
+static struct multiboot_info mbinfo;
61
+
62
+static void multiboot_probe(unsigned char *data, int len)
63
+{
64
+    int offset;
65
+    struct multiboot_header *h;
66
+
67
+    /* Multiboot spec requires the header to be in first 8KB of the image */
68
+    if (len > 8192)
69
+	    len = 8192;
70
+
71
+    for (offset = 0; offset < len; offset += 4) {
72
+	    h = (struct multiboot_header *) (data + offset);
73
+	    if (h->magic == MULTIBOOT_HEADER_MAGIC
74
+			    && h->magic + h->flags + h->checksum == 0) {
75
+		    printf("/Multiboot");
76
+		    mbheader = h;
77
+		    return;
78
+	    }
79
+    }
80
+    mbheader = 0;
81
+}
82
+
83
+static inline void multiboot_boot(unsigned long entry)
84
+{
85
+	unsigned char cmdline[512], *c;
86
+	int i;
87
+	if (!mbheader)
88
+		return;
89
+	/* Etherboot limits the command line to the kernel name,
90
+	 * default parameters and user prompted parameters.  All of
91
+	 * them are shorter than 256 bytes.  As the kernel name and
92
+	 * the default parameters come from the same BOOTP/DHCP entry
93
+	 * (or if they don't, the parameters are empty), only two
94
+	 * strings of the maximum size are possible.  Note this buffer
95
+	 * can overrun if a stupid file name is chosen.  Oh well.  */
96
+	c = cmdline;
97
+	for (i = 0; KERNEL_BUF[i] != 0; i++) {
98
+		switch (KERNEL_BUF[i]) {
99
+		case ' ':
100
+		case '\\':
101
+		case '"':
102
+			*c++ = '\\';
103
+			break;
104
+		default:
105
+			break;
106
+		}
107
+		*c++ = KERNEL_BUF[i];
108
+	}
109
+	(void)sprintf(c, " -retaddr %#lX", virt_to_phys(xend32));
110
+
111
+	mbinfo.flags = MULTIBOOT_MMAP_VALID | MULTIBOOT_MEM_VALID |MULTIBOOT_CMDLINE_VALID;
112
+	mbinfo.memlower = meminfo.basememsize;
113
+	mbinfo.memupper = meminfo.memsize;
114
+	mbinfo.bootdev = 0;	/* not booted from disk */
115
+	mbinfo.cmdline = virt_to_phys(cmdline);
116
+	for (i = 0; i < (int) meminfo.map_count; i++) {
117
+		mbinfo.mmap[i].size = sizeof(struct multiboot_mmap)
118
+		    - sizeof(unsigned int);
119
+		mbinfo.mmap[i].base_addr_low = 
120
+		    (unsigned int) meminfo.map[i].addr;
121
+		mbinfo.mmap[i].base_addr_high = 
122
+		    (unsigned int) (meminfo.map[i].addr >> 32);
123
+		mbinfo.mmap[i].length_low = 
124
+		    (unsigned int) meminfo.map[i].size;
125
+		mbinfo.mmap[i].length_high = 
126
+		    (unsigned int) (meminfo.map[i].size >> 32);
127
+		mbinfo.mmap[i].type = meminfo.map[i].type;
128
+	}
129
+	mbinfo.mmap_length = meminfo.map_count * sizeof(struct multiboot_mmap);
130
+	mbinfo.mmap_addr = virt_to_phys(mbinfo.mmap);
131
+	
132
+	/* The Multiboot 0.6 spec requires all segment registers to be
133
+	 * loaded with an unrestricted, writeable segment.
134
+	 * xstart32 does this for us.
135
+	 */
136
+	
137
+	/* Start the kernel, passing the Multiboot information record
138
+	 * and the magic number.  */
139
+	os_regs.eax = 0x2BADB002;
140
+	os_regs.ebx = virt_to_phys(&mbinfo);
141
+	xstart32(entry);
142
+	longjmp(restart_etherboot, -2);
143
+}

+ 352
- 0
src/arch/i386/core/pci_io.c View File

@@ -0,0 +1,352 @@
1
+/*
2
+** Support for NE2000 PCI clones added David Monro June 1997
3
+** Generalised to other NICs by Ken Yap July 1997
4
+**
5
+** Most of this is taken from:
6
+**
7
+** /usr/src/linux/drivers/pci/pci.c
8
+** /usr/src/linux/include/linux/pci.h
9
+** /usr/src/linux/arch/i386/bios32.c
10
+** /usr/src/linux/include/linux/bios32.h
11
+** /usr/src/linux/drivers/net/ne.c
12
+*/
13
+#ifdef CONFIG_PCI
14
+#include "etherboot.h"
15
+#include "pci.h"
16
+
17
+#ifdef	CONFIG_PCI_DIRECT
18
+#define  PCIBIOS_SUCCESSFUL                0x00
19
+
20
+#define DEBUG 0
21
+
22
+/*
23
+ * Functions for accessing PCI configuration space with type 1 accesses
24
+ */
25
+
26
+#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
27
+
28
+int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn,
29
+			       unsigned int where, uint8_t *value)
30
+{
31
+    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
32
+    *value = inb(0xCFC + (where&3));
33
+    return PCIBIOS_SUCCESSFUL;
34
+}
35
+
36
+int pcibios_read_config_word (unsigned int bus,
37
+    unsigned int device_fn, unsigned int where, uint16_t *value)
38
+{
39
+    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
40
+    *value = inw(0xCFC + (where&2));
41
+    return PCIBIOS_SUCCESSFUL;
42
+}
43
+
44
+int pcibios_read_config_dword (unsigned int bus, unsigned int device_fn,
45
+				 unsigned int where, uint32_t *value)
46
+{
47
+    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
48
+    *value = inl(0xCFC);
49
+    return PCIBIOS_SUCCESSFUL;
50
+}
51
+
52
+int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn,
53
+				 unsigned int where, uint8_t value)
54
+{
55
+    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
56
+    outb(value, 0xCFC + (where&3));
57
+    return PCIBIOS_SUCCESSFUL;
58
+}
59
+
60
+int pcibios_write_config_word (unsigned int bus, unsigned int device_fn,
61
+				 unsigned int where, uint16_t value)
62
+{
63
+    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
64
+    outw(value, 0xCFC + (where&2));
65
+    return PCIBIOS_SUCCESSFUL;
66
+}
67
+
68
+int pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, uint32_t value)
69
+{
70
+    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
71
+    outl(value, 0xCFC);
72
+    return PCIBIOS_SUCCESSFUL;
73
+}
74
+
75
+#undef CONFIG_CMD
76
+
77
+#else	 /* CONFIG_PCI_DIRECT  not defined */
78
+
79
+#if !defined(PCBIOS)
80
+#error "The pcibios can only be used when the PCBIOS support is compiled in"
81
+#endif
82
+
83
+/* Macro for calling the BIOS32 service.  This replaces the old
84
+ * bios32_call function.  Use in a statement such as
85
+ * __asm__ ( BIOS32_CALL,
86
+ *	     : <output registers>
87
+ *	     : "S" ( bios32_entry ), <other input registers> );
88
+ */
89
+#define BIOS32_CALL "call _virt_to_phys\n\t" \
90
+		    "pushl %%cs\n\t" \
91
+		    "call *%%esi\n\t" \
92
+		    "cli\n\t" \
93
+		    "cld\n\t" \
94
+		    "call _phys_to_virt\n\t"
95
+
96
+static unsigned long bios32_entry;
97
+static unsigned long pcibios_entry;
98
+
99
+static unsigned long bios32_service(unsigned long service)
100
+{
101
+	unsigned char return_code;	/* %al */
102
+	unsigned long address;		/* %ebx */
103
+	unsigned long length;		/* %ecx */
104
+	unsigned long entry;		/* %edx */
105
+
106
+	__asm__(BIOS32_CALL
107
+		: "=a" (return_code),
108
+		  "=b" (address),
109
+		  "=c" (length),
110
+		  "=d" (entry)
111
+		: "0" (service),
112
+		  "1" (0),
113
+		  "S" (bios32_entry));
114
+
115
+	switch (return_code) {
116
+		case 0:
117
+			return address + entry;
118
+		case 0x80:	/* Not present */
119
+			printf("bios32_service(%d) : not present\n", service);
120
+			return 0;
121
+		default: /* Shouldn't happen */
122
+			printf("bios32_service(%d) : returned %#X????\n",
123
+				service, return_code);
124
+			return 0;
125
+	}
126
+}
127
+
128
+int pcibios_read_config_byte(unsigned int bus,
129
+        unsigned int device_fn, unsigned int where, uint8_t *value)
130
+{
131
+        unsigned long ret;
132
+        unsigned long bx = (bus << 8) | device_fn;
133
+
134
+        __asm__(BIOS32_CALL
135
+                "jc 1f\n\t"
136
+                "xor %%ah, %%ah\n"
137
+                "1:"
138
+                : "=c" (*value),
139
+                  "=a" (ret)
140
+                : "1" (PCIBIOS_READ_CONFIG_BYTE),
141
+                  "b" (bx),
142
+                  "D" ((long) where),
143
+                  "S" (pcibios_entry));
144
+        return (int) (ret & 0xff00) >> 8;
145
+}
146
+
147
+int pcibios_read_config_word(unsigned int bus,
148
+        unsigned int device_fn, unsigned int where, uint16_t *value)
149
+{
150
+        unsigned long ret;
151
+        unsigned long bx = (bus << 8) | device_fn;
152
+
153
+        __asm__(BIOS32_CALL
154
+                "jc 1f\n\t"
155
+                "xor %%ah, %%ah\n"
156
+                "1:"
157
+                : "=c" (*value),
158
+                  "=a" (ret)
159
+                : "1" (PCIBIOS_READ_CONFIG_WORD),
160
+                  "b" (bx),
161
+                  "D" ((long) where),
162
+                  "S" (pcibios_entry));
163
+        return (int) (ret & 0xff00) >> 8;
164
+}
165
+
166
+int pcibios_read_config_dword(unsigned int bus,
167
+        unsigned int device_fn, unsigned int where, uint32_t *value)
168
+{
169
+        unsigned long ret;
170
+        unsigned long bx = (bus << 8) | device_fn;
171
+
172
+        __asm__(BIOS32_CALL
173
+                "jc 1f\n\t"
174
+                "xor %%ah, %%ah\n"
175
+                "1:"
176
+                : "=c" (*value),
177
+                  "=a" (ret)
178
+                : "1" (PCIBIOS_READ_CONFIG_DWORD),
179
+                  "b" (bx),
180
+                  "D" ((long) where),
181
+                  "S" (pcibios_entry));
182
+        return (int) (ret & 0xff00) >> 8;
183
+}
184
+
185
+int pcibios_write_config_byte (unsigned int bus,
186
+	unsigned int device_fn, unsigned int where, uint8_t value)
187
+{
188
+	unsigned long ret;
189
+	unsigned long bx = (bus << 8) | device_fn;
190
+
191
+	__asm__(BIOS32_CALL
192
+		"jc 1f\n\t"
193
+		"xor %%ah, %%ah\n"
194
+		"1:"
195
+		: "=a" (ret)
196
+		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
197
+		  "c" (value),
198
+		  "b" (bx),
199
+		  "D" ((long) where),
200
+		  "S" (pcibios_entry));
201
+	return (int) (ret & 0xff00) >> 8;
202
+}
203
+
204
+int pcibios_write_config_word (unsigned int bus,
205
+	unsigned int device_fn, unsigned int where, uint16_t value)
206
+{
207
+	unsigned long ret;
208
+	unsigned long bx = (bus << 8) | device_fn;
209
+
210
+	__asm__(BIOS32_CALL
211
+		"jc 1f\n\t"
212
+		"xor %%ah, %%ah\n"
213
+		"1:"
214
+		: "=a" (ret)
215
+		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
216
+		  "c" (value),
217
+		  "b" (bx),
218
+		  "D" ((long) where),
219
+		  "S" (pcibios_entry));
220
+	return (int) (ret & 0xff00) >> 8;
221
+}
222
+
223
+int pcibios_write_config_dword (unsigned int bus,
224
+	unsigned int device_fn, unsigned int where, uint32_t value)
225
+{
226
+	unsigned long ret;
227
+	unsigned long bx = (bus << 8) | device_fn;
228
+
229
+	__asm__(BIOS32_CALL
230
+		"jc 1f\n\t"
231
+		"xor %%ah, %%ah\n"
232
+		"1:"
233
+		: "=a" (ret)
234
+		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
235
+		  "c" (value),
236
+		  "b" (bx),
237
+		  "D" ((long) where),
238
+		  "S" (pcibios_entry));
239
+	return (int) (ret & 0xff00) >> 8;
240
+}
241
+
242
+static void check_pcibios(void)
243
+{
244
+	unsigned long signature;
245
+	unsigned char present_status;
246
+	unsigned char major_revision;
247
+	unsigned char minor_revision;
248
+	int pack;
249
+
250
+	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
251
+		__asm__(BIOS32_CALL
252
+			"jc 1f\n\t"
253
+			"xor %%ah, %%ah\n"
254
+			"1:\tshl $8, %%eax\n\t"
255
+			"movw %%bx, %%ax"
256
+			: "=d" (signature),
257
+			  "=a" (pack)
258
+			: "1" (PCIBIOS_PCI_BIOS_PRESENT),
259
+			  "S" (pcibios_entry)
260
+			: "bx", "cx");
261
+
262
+		present_status = (pack >> 16) & 0xff;
263
+		major_revision = (pack >> 8) & 0xff;
264
+		minor_revision = pack & 0xff;
265
+		if (present_status || (signature != PCI_SIGNATURE)) {
266
+			printf("ERROR: BIOS32 says PCI BIOS, but no PCI "
267
+				"BIOS????\n");
268
+			pcibios_entry = 0;
269
+		}
270
+#if	DEBUG
271
+		if (pcibios_entry) {
272
+			printf ("pcibios_init : PCI BIOS revision %hhX.%hhX"
273
+				" entry at %#X\n", major_revision,
274
+				minor_revision, pcibios_entry);
275
+		}
276
+#endif
277
+	}
278
+}
279
+
280
+static void pcibios_init(void)
281
+{
282
+	union bios32 *check;
283
+	unsigned char sum;
284
+	int i, length;
285
+	bios32_entry = 0;
286
+
287
+	/*
288
+	 * Follow the standard procedure for locating the BIOS32 Service
289
+	 * directory by scanning the permissible address range from
290
+	 * 0xe0000 through 0xfffff for a valid BIOS32 structure.
291
+	 *
292
+	 */
293
+
294
+	for (check = phys_to_virt(0xe0000); (void *)check <= phys_to_virt(0xffff0); ++check) {
295
+		if (check->fields.signature != BIOS32_SIGNATURE)
296
+			continue;
297
+		length = check->fields.length * 16;
298
+		if (!length)
299
+			continue;
300
+		sum = 0;
301
+		for (i = 0; i < length ; ++i)
302
+			sum += check->chars[i];
303
+		if (sum != 0)
304
+			continue;
305
+		if (check->fields.revision != 0) {
306
+			printf("pcibios_init : unsupported revision %d at %#X, mail drew@colorado.edu\n",
307
+				check->fields.revision, check);
308
+			continue;
309
+		}
310
+#if	DEBUG
311
+		printf("pcibios_init : BIOS32 Service Directory "
312
+			"structure at %#X\n", check);
313
+#endif
314
+		if (!bios32_entry) {
315
+			if (check->fields.entry >= 0x100000) {
316
+				printf("pcibios_init: entry in high "
317
+					"memory, giving up\n");
318
+				return;
319
+			} else {
320
+				bios32_entry = check->fields.entry;
321
+#if	DEBUG
322
+				printf("pcibios_init : BIOS32 Service Directory"
323
+					" entry at %#X\n", bios32_entry);
324
+#endif
325
+			}
326
+		}
327
+	}
328
+	if (bios32_entry)
329
+		check_pcibios();
330
+}
331
+#endif	/* CONFIG_PCI_DIRECT not defined*/
332
+
333
+unsigned long pcibios_bus_base(unsigned int bus __unused)
334
+{
335
+	/* architecturally this must be 0 */
336
+	return 0;
337
+}
338
+
339
+void find_pci(int type, struct pci_device *dev)
340
+{
341
+#ifndef	CONFIG_PCI_DIRECT
342
+	if (!pcibios_entry) {
343
+		pcibios_init();
344
+	}
345
+	if (!pcibios_entry) {
346
+		printf("pci_init: no BIOS32 detected\n");
347
+		return;
348
+	}
349
+#endif
350
+	return scan_pci_bus(type, dev);
351
+}
352
+#endif /* CONFIG_PCI */

+ 331
- 0
src/arch/i386/core/pic8259.c View File

@@ -0,0 +1,331 @@
1
+/*
2
+ * Basic support for controlling the 8259 Programmable Interrupt Controllers.
3
+ *
4
+ * Initially written by Michael Brown (mcb30).
5
+ */
6
+
7
+#include <etherboot.h>
8
+#include "pic8259.h"
9
+#include "realmode.h"
10
+
11
+#ifdef DEBUG_IRQ
12
+#define DBG(...) printf ( __VA_ARGS__ )
13
+#else
14
+#define DBG(...)
15
+#endif
16
+
17
+/* State of trivial IRQ handler */
18
+irq_t trivial_irq_installed_on = IRQ_NONE;
19
+static uint16_t trivial_irq_previous_trigger_count = 0;
20
+
21
+/* The actual trivial IRQ handler
22
+ *
23
+ * Note: we depend on the C compiler not realising that we're putting
24
+ * variables in the ".text16" section and therefore not forcing them
25
+ * back to the ".data" section.  I don't see any reason to expect this
26
+ * behaviour to change.
27
+ *
28
+ * These must *not* be the first variables to appear in this file; the
29
+ * first variable to appear gets the ".data" directive.
30
+ */
31
+RM_FRAGMENT(_trivial_irq_handler,
32
+	"pushw %bx\n\t"
33
+	"call  1f\n1:\tpopw %bx\n\t"   /* PIC access to variables */
34
+	"incw  %cs:(_trivial_irq_trigger_count-1b)(%bx)\n\t" 
35
+	"popw  %bx\n\t" 
36
+	"iret\n\t" 
37
+	"\n\t"
38
+	".globl _trivial_irq_trigger_count\n\t"
39
+	"_trivial_irq_trigger_count: .short 0\n\t"
40
+	"\n\t"
41
+	".globl _trivial_irq_chain_to\n\t"
42
+	"_trivial_irq_chain_to: .short 0,0\n\t"
43
+	"\n\t"
44
+	".globl _trivial_irq_chain\n\t"
45
+	"_trivial_irq_chain: .byte 0\n\t"
46
+	);
47
+extern volatile uint16_t _trivial_irq_trigger_count;
48
+extern segoff_t _trivial_irq_chain_to;
49
+extern int8_t _trivial_irq_chain;
50
+
51
+/* Current locations of trivial IRQ handler.  These will change at
52
+ * runtime when relocation is used; the handler needs to be copied to
53
+ * base memory before being installed.
54
+ */
55
+void (*trivial_irq_handler)P((void)) = _trivial_irq_handler;
56
+uint16_t volatile *trivial_irq_trigger_count = &_trivial_irq_trigger_count;
57
+segoff_t *trivial_irq_chain_to = &_trivial_irq_chain_to;
58
+uint8_t *trivial_irq_chain = &_trivial_irq_chain;
59
+
60
+/* Install a handler for the specified IRQ.  Address of previous
61
+ * handler will be stored in previous_handler.  Enabled/disabled state
62
+ * of IRQ will be preserved across call, therefore if the handler does
63
+ * chaining, ensure that either (a) IRQ is disabled before call, or
64
+ * (b) previous_handler points directly to the place that the handler
65
+ * picks up its chain-to address.
66
+ */
67
+
68
+int install_irq_handler ( irq_t irq, segoff_t *handler,
69
+			  uint8_t *previously_enabled,
70
+			  segoff_t *previous_handler ) {
71
+	segoff_t *irq_vector = IRQ_VECTOR ( irq );
72
+	*previously_enabled = irq_enabled ( irq );
73
+
74
+	if ( irq > IRQ_MAX ) {
75
+		DBG ( "Invalid IRQ number %d\n" );
76
+		return 0;
77
+	}
78
+
79
+	previous_handler->segment = irq_vector->segment;
80
+	previous_handler->offset = irq_vector->offset;
81
+	if ( *previously_enabled ) disable_irq ( irq );
82
+	DBG ( "Installing handler at %hx:%hx for IRQ %d (vector 0000:%hx),"
83
+	      " leaving %s\n",
84
+	      handler->segment, handler->offset, irq, virt_to_phys(irq_vector),
85
+	      ( *previously_enabled ? "enabled" : "disabled" ) );
86
+	DBG ( "...(previous handler at %hx:%hx)\n",
87
+	      previous_handler->segment, previous_handler->offset );
88
+	irq_vector->segment = handler->segment;
89
+	irq_vector->offset = handler->offset;
90
+	if ( *previously_enabled ) enable_irq ( irq );
91
+	return 1;
92
+}
93
+
94
+/* Remove handler for the specified IRQ.  Routine checks that another
95
+ * handler has not been installed that chains to handler before
96
+ * uninstalling handler.  Enabled/disabled state of the IRQ will be
97
+ * restored to that specified by previously_enabled.
98
+ */
99
+
100
+int remove_irq_handler ( irq_t irq, segoff_t *handler,
101
+			 uint8_t *previously_enabled,
102
+			 segoff_t *previous_handler ) {
103
+	segoff_t *irq_vector = IRQ_VECTOR ( irq );
104
+
105
+	if ( irq > IRQ_MAX ) {
106
+		DBG ( "Invalid IRQ number %d\n" );
107
+		return 0;
108
+	}
109
+	if ( ( irq_vector->segment != handler->segment ) ||
110
+	     ( irq_vector->offset != handler->offset ) ) {
111
+		DBG ( "Cannot remove handler for IRQ %d\n" );
112
+		return 0;
113
+	}
114
+
115
+	DBG ( "Removing handler for IRQ %d\n", irq );
116
+	disable_irq ( irq );
117
+	irq_vector->segment = previous_handler->segment;
118
+	irq_vector->offset = previous_handler->offset;
119
+	if ( *previously_enabled ) enable_irq ( irq );
120
+	return 1;
121
+}
122
+
123
+/* Install the trivial IRQ handler.  This routine installs the
124
+ * handler, tests it and enables the IRQ.
125
+ */
126
+
127
+int install_trivial_irq_handler ( irq_t irq ) {
128
+	segoff_t trivial_irq_handler_segoff = SEGOFF(trivial_irq_handler);
129
+	
130
+	if ( trivial_irq_installed_on != IRQ_NONE ) {
131
+		DBG ( "Can install trivial IRQ handler only once\n" );
132
+		return 0;
133
+	}
134
+	if ( SEGMENT(trivial_irq_handler) > 0xffff ) {
135
+		DBG ( "Trivial IRQ handler not in base memory\n" );
136
+		return 0;
137
+	}
138
+
139
+	DBG ( "Installing trivial IRQ handler on IRQ %d\n", irq );
140
+	if ( ! install_irq_handler ( irq, &trivial_irq_handler_segoff,
141
+				     trivial_irq_chain,
142
+				     trivial_irq_chain_to ) )
143
+		return 0;
144
+	trivial_irq_installed_on = irq;
145
+
146
+	DBG ( "Testing trivial IRQ handler\n" );
147
+	disable_irq ( irq );
148
+	*trivial_irq_trigger_count = 0;
149
+	trivial_irq_previous_trigger_count = 0;
150
+	fake_irq ( irq );
151
+	if ( ! trivial_irq_triggered ( irq ) ) {
152
+		DBG ( "Installation of trivial IRQ handler failed\n" );
153
+		remove_trivial_irq_handler ( irq );
154
+		return 0;
155
+	}
156
+	/* Send EOI just in case there was a leftover interrupt */
157
+	send_specific_eoi ( irq );
158
+	DBG ( "Trivial IRQ handler installed successfully\n" );
159
+	enable_irq ( irq );
160
+	return 1;
161
+}
162
+
163
+/* Remove the trivial IRQ handler.
164
+ */
165
+
166
+int remove_trivial_irq_handler ( irq_t irq ) {
167
+	segoff_t trivial_irq_handler_segoff = SEGOFF(trivial_irq_handler);
168
+
169
+	if ( trivial_irq_installed_on == IRQ_NONE ) return 1;
170
+	if ( irq != trivial_irq_installed_on ) {
171
+		DBG ( "Cannot uninstall trivial IRQ handler from IRQ %d; "
172
+		      "is installed on IRQ %d\n", irq,
173
+		      trivial_irq_installed_on );
174
+		return 0;
175
+	}
176
+
177
+	if ( ! remove_irq_handler ( irq, &trivial_irq_handler_segoff,
178
+				    trivial_irq_chain,
179
+				    trivial_irq_chain_to ) )
180
+		return 0;
181
+
182
+	if ( trivial_irq_triggered ( trivial_irq_installed_on ) ) {
183
+		DBG ( "Sending EOI for unwanted trivial IRQ\n" );
184
+		send_specific_eoi ( trivial_irq_installed_on );
185
+	}
186
+
187
+	trivial_irq_installed_on = IRQ_NONE;
188
+	return 1;
189
+}
190
+
191
+/* Safe method to detect whether or not trivial IRQ has been
192
+ * triggered.  Using this call avoids potential race conditions.  This
193
+ * call will return success only once per trigger.
194
+ */
195
+
196
+int trivial_irq_triggered ( irq_t irq ) {
197
+	uint16_t trivial_irq_this_trigger_count = *trivial_irq_trigger_count;
198
+	int triggered = ( trivial_irq_this_trigger_count -
199
+			  trivial_irq_previous_trigger_count );
200
+	
201
+	/* irq is not used at present, but we have it in the API for
202
+	 * future-proofing; in case we want the facility to have
203
+	 * multiple trivial IRQ handlers installed simultaneously.
204
+	 *
205
+	 * Avoid compiler warning about unused variable.
206
+	 */
207
+	if ( irq == IRQ_NONE ) {};
208
+	
209
+	trivial_irq_previous_trigger_count = trivial_irq_this_trigger_count;
210
+	return triggered ? 1 : 0;
211
+}
212
+
213
+/* Copy trivial IRQ handler to a new location.  Typically used to copy
214
+ * the handler into base memory; when relocation is being used we need
215
+ * to do this before installing the handler.
216
+ *
217
+ * Call with target=NULL in order to restore the handler to its
218
+ * original location.
219
+ */
220
+
221
+int copy_trivial_irq_handler ( void *target, size_t target_size ) {
222
+	irq_t currently_installed_on = trivial_irq_installed_on;
223
+	uint32_t offset = ( target == NULL ? 0 :
224
+			    target - (void*)_trivial_irq_handler );
225
+
226
+	if (( target != NULL ) && ( target_size < TRIVIAL_IRQ_HANDLER_SIZE )) {
227
+		DBG ( "Insufficient space to copy trivial IRQ handler\n" );
228
+		return 0;
229
+	}
230
+
231
+	if ( currently_installed_on != IRQ_NONE ) {
232
+		DBG ("WARNING: relocating trivial IRQ handler while in use\n");
233
+		if ( ! remove_trivial_irq_handler ( currently_installed_on ) )
234
+			return 0;
235
+	}
236
+
237
+	/* Do the actual copy */
238
+	if ( target != NULL ) {
239
+		DBG ( "Copying trivial IRQ handler to %hx:%hx\n",
240
+		      SEGMENT(target), OFFSET(target) );
241
+		memcpy ( target, _trivial_irq_handler,
242
+			 TRIVIAL_IRQ_HANDLER_SIZE );
243
+	} else {
244
+		DBG ( "Restoring trivial IRQ handler to original location\n" );
245
+	}
246
+	/* Update all the pointers to structures within the handler */
247
+	trivial_irq_handler = ( void (*)P((void)) )
248
+		( (void*)_trivial_irq_handler + offset );
249
+	trivial_irq_trigger_count = (uint16_t*)
250
+		( (void*)&_trivial_irq_trigger_count + offset );
251
+	trivial_irq_chain_to = (segoff_t*)
252
+		( (void*)&_trivial_irq_chain_to + offset );
253
+	trivial_irq_chain = (uint8_t*)
254
+		( (void*)&_trivial_irq_chain + offset );
255
+
256
+	if ( currently_installed_on != IRQ_NONE ) {
257
+		if ( ! install_trivial_irq_handler ( currently_installed_on ) )
258
+			return 0;
259
+	}
260
+	return 1;
261
+}
262
+
263
+/* Send non-specific EOI(s).  This seems to be inherently unsafe.
264
+ */
265
+
266
+void send_nonspecific_eoi ( irq_t irq ) {
267
+	DBG ( "Sending non-specific EOI for IRQ %d\n", irq );
268
+	if ( irq >= IRQ_PIC_CUTOFF ) {
269
+		outb ( ICR_EOI_NON_SPECIFIC, PIC2_ICR );
270
+	}		
271
+	outb ( ICR_EOI_NON_SPECIFIC, PIC1_ICR );
272
+}
273
+
274
+/* Send specific EOI(s).
275
+ */
276
+
277
+void send_specific_eoi ( irq_t irq ) {
278
+	DBG ( "Sending specific EOI for IRQ %d\n", irq );
279
+	outb ( ICR_EOI_SPECIFIC | ICR_VALUE(irq), ICR_REG(irq) );
280
+	if ( irq >= IRQ_PIC_CUTOFF ) {
281
+		outb ( ICR_EOI_SPECIFIC | ICR_VALUE(CHAINED_IRQ),
282
+		       ICR_REG(CHAINED_IRQ) );
283
+	}
284
+}
285
+
286
+/* Fake an IRQ
287
+ */
288
+
289
+void fake_irq ( irq_t irq ) {
290
+	struct {
291
+		uint16_t int_number;
292
+	} PACKED in_stack;
293
+
294
+	/* Convert IRQ to INT number:
295
+	 *
296
+	 * subb	$0x08,%cl	Invert bit 3, set bits 4-7 iff irq < 8
297
+	 * xorb	$0x70,%cl	Invert bits 4-6
298
+	 * andb	$0x7f,%cl	Clear bit 7
299
+	 *
300
+	 * No, it's not the most intuitive method, but I was proud to
301
+	 * get it down to three lines of assembler when this routine
302
+	 * was originally implemented in pcbios.S.
303
+	 */
304
+	in_stack.int_number = ( ( irq - 8 ) ^ 0x70 ) & 0x7f;
305
+
306
+	RM_FRAGMENT(rm_fake_irq,
307
+		"popw %ax\n\t"		/* %ax = INT number */
308
+		"call 1f\n1:\tpop %bx\n\t"
309
+		"movb %al, %cs:(2f-1b+1)(%bx)\n\t" /* Overwrite INT number..*/
310
+		"\n2:\tint $0x00\n\t"		    /* ..in this instruction */
311
+	);
312
+
313
+	real_call ( rm_fake_irq, &in_stack, NULL );
314
+}
315
+
316
+/* Dump current 8259 status: enabled IRQs and handler addresses.
317
+ */
318
+
319
+#ifdef DEBUG_IRQ
320
+void dump_irq_status ( void ) {
321
+	int irq = 0;
322
+	
323
+	for ( irq = 0; irq < 16; irq++ ) {
324
+		if ( irq_enabled ( irq ) ) {
325
+			printf ( "IRQ%d enabled, ISR at %hx:%hx\n", irq,
326
+				 IRQ_VECTOR(irq)->segment,
327
+				 IRQ_VECTOR(irq)->offset );
328
+		}
329
+	}
330
+}
331
+#endif

+ 8
- 0
src/arch/i386/core/prefixudata.lds View File

@@ -0,0 +1,8 @@
1
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2
+OUTPUT_ARCH(i386)
3
+
4
+SECTIONS {
5
+	 .prefix.udata : {
6
+		      *(*)
7
+	 }
8
+}

+ 8
- 0
src/arch/i386/core/prefixzdata.lds View File

@@ -0,0 +1,8 @@
1
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2
+OUTPUT_ARCH(i386)
3
+
4
+SECTIONS {
5
+	 .prefix.zdata : {
6
+		      *(*)
7
+	 }
8
+}

+ 364
- 0
src/arch/i386/core/pxe_callbacks.c View File

@@ -0,0 +1,364 @@
1
+/* PXE callback mechanisms.  This file contains only the portions
2
+ * specific to i386: i.e. the low-level mechanisms for calling in from
3
+ * an NBP to the PXE stack and for starting an NBP from the PXE stack.
4
+ */
5
+
6
+#ifdef PXE_EXPORT
7
+
8
+#include "etherboot.h"
9
+#include "callbacks.h"
10
+#include "realmode.h"
11
+#include "pxe.h"
12
+#include "pxe_callbacks.h"
13
+#include "pxe_export.h"
14
+#include "hidemem.h"
15
+#include <stdarg.h>
16
+
17
+#define INSTALLED(x) ( (typeof(&x)) ( (void*)(&x) \
18
+				      - &pxe_callback_interface \
19
+				      + (void*)&pxe_stack->arch_data ) )
20
+#define pxe_intercept_int1a	INSTALLED(_pxe_intercept_int1a)
21
+#define pxe_intercepted_int1a	INSTALLED(_pxe_intercepted_int1a)
22
+#define pxe_pxenv_location	INSTALLED(_pxe_pxenv_location)
23
+#define INT1A_VECTOR ( (segoff_t*) ( phys_to_virt( 4 * 0x1a ) ) )
24
+
25
+/* The overall size of the PXE stack is ( sizeof(pxe_stack_t) +
26
+ * pxe_callback_interface_size + rm_callback_interface_size ).
27
+ * Unfortunately, this isn't a compile-time constant, since
28
+ * {pxe,rm}_callback_interface_size depend on the length of the
29
+ * assembly code in these interfaces.
30
+ *
31
+ * We used to have a function pxe_stack_size() which returned this
32
+ * value.  However, it actually needs to be a link-time constant, so
33
+ * that it can appear in the UNDIROMID structure in romprefix.S.  We
34
+ * therefore export the three component sizes as absolute linker
35
+ * symbols, get the linker to add them together and generate a new
36
+ * absolute symbol _pxe_stack_size.  We then import this value into a
37
+ * C variable pxe_stack_size, for access from C code.
38
+ */
39
+
40
+/* gcc won't let us use extended asm outside a function (compiler
41
+ * bug), ao we have to put these asm statements inside a dummy
42
+ * function.
43
+ */
44
+static void work_around_gcc_bug ( void ) __attribute__ ((used));
45
+static void work_around_gcc_bug ( void ) {
46
+	/* Export sizeof(pxe_stack_t) as absolute linker symbol */
47
+	__asm__ ( ".globl _pxe_stack_t_size" );
48
+	__asm__ ( ".equ _pxe_stack_t_size, %c0"
49
+		  : : "i" (sizeof(pxe_stack_t)) );
50
+}
51
+/* Import _pxe_stack_size absolute linker symbol into C variable */
52
+extern int pxe_stack_size;
53
+__asm__ ( "pxe_stack_size: .long _pxe_stack_size" );
54
+
55
+/* Utility routine: byte checksum
56
+ */
57
+uint8_t byte_checksum ( void *address, size_t size ) {
58
+	unsigned int i, sum = 0;
59
+
60
+	for ( i = 0; i < size; i++ ) {
61
+		sum += ((uint8_t*)address)[i];
62
+	}
63
+	return (uint8_t)sum;
64
+}
65
+
66
+/* install_pxe_stack(): install PXE stack.
67
+ * 
68
+ * Use base = NULL for auto-allocation of base memory
69
+ *
70
+ * IMPORTANT: no further allocation of base memory should take place
71
+ * before the PXE stack is removed.  This is to work around a small
72
+ * but important deficiency in the PXE specification.
73
+ */
74
+pxe_stack_t * install_pxe_stack ( void *base ) {
75
+	pxe_t *pxe;
76
+	pxenv_t *pxenv;
77
+	void *pxe_callback_code;
78
+	void (*pxe_in_call_far)(void);
79
+	void (*pxenv_in_call_far)(void);
80
+	void *rm_callback_code;
81
+	void *e820mangler_code;
82
+	void *end;
83
+
84
+	/* If already installed, just return */
85
+	if ( pxe_stack != NULL ) return pxe_stack;
86
+
87
+	/* Allocate base memory if requested to do so
88
+	 */
89
+	if ( base == NULL ) {
90
+		base = allot_base_memory ( pxe_stack_size );
91
+		if ( base == NULL ) return NULL;
92
+	}
93
+
94
+	/* Round address up to 16-byte physical alignment */
95
+	pxe_stack = (pxe_stack_t *)
96
+		( phys_to_virt ( ( virt_to_phys(base) + 0xf ) & ~0xf ) );
97
+	/* Zero out allocated stack */
98
+	memset ( pxe_stack, 0, sizeof(*pxe_stack) );
99
+	
100
+	/* Calculate addresses for portions of the stack */
101
+	pxe = &(pxe_stack->pxe);
102
+	pxenv = &(pxe_stack->pxenv);
103
+	pxe_callback_code = &(pxe_stack->arch_data);
104
+	pxe_in_call_far = _pxe_in_call_far +  
105
+		( pxe_callback_code - &pxe_callback_interface );
106
+	pxenv_in_call_far = _pxenv_in_call_far +
107
+		( pxe_callback_code - &pxe_callback_interface );
108
+	rm_callback_code = pxe_callback_code + pxe_callback_interface_size;
109
+	
110
+	e820mangler_code = (void*)(((int)rm_callback_code +
111
+				    rm_callback_interface_size + 0xf ) & ~0xf);
112
+	end = e820mangler_code + e820mangler_size;
113
+
114
+	/* Initialise !PXE data structures */
115
+	memcpy ( pxe->Signature, "!PXE", 4 );
116
+	pxe->StructLength = sizeof(*pxe);
117
+	pxe->StructRev = 0;
118
+	pxe->reserved_1 = 0;
119
+	/* We don't yet have an UNDI ROM ID structure */
120
+	pxe->UNDIROMID.segment = 0;
121
+	pxe->UNDIROMID.offset = 0;
122
+	/* or a BC ROM ID structure */
123
+	pxe->BaseROMID.segment = 0;
124
+	pxe->BaseROMID.offset = 0;
125
+	pxe->EntryPointSP.segment = SEGMENT(pxe_stack);
126
+	pxe->EntryPointSP.offset = (void*)pxe_in_call_far - (void*)pxe_stack;
127
+	/* No %esp-compatible entry point yet */
128
+	pxe->EntryPointESP.segment = 0;
129
+	pxe->EntryPointESP.offset = 0;
130
+	pxe->StatusCallout.segment = -1;
131
+	pxe->StatusCallout.offset = -1;
132
+	pxe->reserved_2 = 0;
133
+	pxe->SegDescCn = 7;
134
+	pxe->FirstSelector = 0;
135
+	/* PXE specification doesn't say anything about when the stack
136
+	 * space should get freed.  We work around this by claiming it
137
+	 * as our data segment as well.
138
+	 */
139
+	pxe->Stack.Seg_Addr = pxe->UNDIData.Seg_Addr = real_mode_stack >> 4;
140
+	pxe->Stack.Phy_Addr = pxe->UNDIData.Phy_Addr = real_mode_stack;
141
+	pxe->Stack.Seg_Size = pxe->UNDIData.Seg_Size = real_mode_stack_size;
142
+	/* Code segment has to be the one containing the data structures... */
143
+	pxe->UNDICode.Seg_Addr = SEGMENT(pxe_stack);
144
+	pxe->UNDICode.Phy_Addr = virt_to_phys(pxe_stack);
145
+	pxe->UNDICode.Seg_Size = end - (void*)pxe_stack;
146
+	/* No base code loaded */
147
+	pxe->BC_Data.Seg_Addr = 0;
148
+	pxe->BC_Data.Phy_Addr = 0;
149
+	pxe->BC_Data.Seg_Size = 0;
150
+	pxe->BC_Code.Seg_Addr = 0;
151
+	pxe->BC_Code.Phy_Addr = 0;
152
+	pxe->BC_Code.Seg_Size = 0;
153
+	pxe->BC_CodeWrite.Seg_Addr = 0;
154
+	pxe->BC_CodeWrite.Phy_Addr = 0;
155
+	pxe->BC_CodeWrite.Seg_Size = 0;
156
+	pxe->StructCksum -= byte_checksum ( pxe, sizeof(*pxe) );
157
+
158
+	/* Initialise PXENV+ data structures */
159
+	memcpy ( pxenv->Signature, "PXENV+", 6 );
160
+	pxenv->Version = 0x201;
161
+	pxenv->Length = sizeof(*pxenv);
162
+	pxenv->RMEntry.segment = SEGMENT(pxe_stack);
163
+	pxenv->RMEntry.offset = (void*)pxenv_in_call_far - (void*)pxe_stack;
164
+	pxenv->PMOffset = 0; /* "Do not use" says the PXE spec */
165
+	pxenv->PMSelector = 0; /* "Do not use" says the PXE spec */
166
+	pxenv->StackSeg = pxenv->UNDIDataSeg = real_mode_stack >> 4;
167
+	pxenv->StackSize = pxenv->UNDIDataSize = real_mode_stack_size;
168
+	pxenv->BC_CodeSeg = 0;
169
+	pxenv->BC_CodeSize = 0;
170
+	pxenv->BC_DataSeg = 0;
171
+	pxenv->BC_DataSize = 0;
172
+	/* UNDIData{Seg,Size} set above */
173
+	pxenv->UNDICodeSeg = SEGMENT(pxe_stack);
174
+	pxenv->UNDICodeSize = end - (void*)pxe_stack;
175
+	pxenv->PXEPtr.segment = SEGMENT(pxe);
176
+	pxenv->PXEPtr.offset = OFFSET(pxe);
177
+	pxenv->Checksum -= byte_checksum ( pxenv, sizeof(*pxenv) );
178
+
179
+	/* Mark stack as inactive */
180
+	pxe_stack->state = CAN_UNLOAD;
181
+
182
+	/* Install PXE and RM callback code and E820 mangler */
183
+	memcpy ( pxe_callback_code, &pxe_callback_interface,
184
+		 pxe_callback_interface_size );
185
+	install_rm_callback_interface ( rm_callback_code, 0 );
186
+	install_e820mangler ( e820mangler_code );
187
+
188
+	return pxe_stack;
189
+}
190
+
191
+/* Use the UNDI data segment as our real-mode stack.  This is for when
192
+ * we have been loaded via the UNDI loader
193
+ */
194
+void use_undi_ds_for_rm_stack ( uint16_t ds ) {
195
+	forget_real_mode_stack();
196
+	real_mode_stack = virt_to_phys ( VIRTUAL ( ds, 0 ) );
197
+	lock_real_mode_stack = 1;
198
+}
199
+
200
+/* Activate PXE stack (i.e. hook interrupt vectors).  The PXE stack
201
+ * *can* be used before it is activated, but it really shoudln't.
202
+ */
203
+int hook_pxe_stack ( void ) {
204
+	if ( pxe_stack == NULL ) return 0;
205
+	if ( pxe_stack->state >= MIDWAY ) return 1;
206
+
207
+	/* Hook INT15 handler */
208
+	hide_etherboot();
209
+
210
+	/* Hook INT1A handler */
211
+	*pxe_intercepted_int1a = *INT1A_VECTOR;
212
+	pxe_pxenv_location->segment = SEGMENT(pxe_stack);
213
+	pxe_pxenv_location->offset = (void*)&pxe_stack->pxenv
214
+		- (void*)pxe_stack;
215
+	INT1A_VECTOR->segment = SEGMENT(&pxe_stack->arch_data);
216
+	INT1A_VECTOR->offset = (void*)pxe_intercept_int1a
217
+		- (void*)&pxe_stack->arch_data;
218
+
219
+	/* Mark stack as active */
220
+	pxe_stack->state = MIDWAY;
221
+	return 1;
222
+}
223
+
224
+/* Deactivate the PXE stack (i.e. unhook interrupt vectors).
225
+ */
226
+int unhook_pxe_stack ( void ) {
227
+	if ( pxe_stack == NULL ) return 0;
228
+	if ( pxe_stack->state <= CAN_UNLOAD ) return 1;
229
+
230
+	/* Restore original INT15 and INT1A handlers */
231
+	*INT1A_VECTOR = *pxe_intercepted_int1a;
232
+	if ( !unhide_etherboot() ) {
233
+		/* Cannot unhook INT15.  We're up the creek without
234
+		 * even a suitable log out of which to fashion a
235
+		 * paddle.  There are some very badly behaved NBPs
236
+		 * that will ignore plaintive pleas such as
237
+		 * PXENV_KEEP_UNDI and just zero out our code anyway.
238
+		 * This means they end up vapourising an active INT15
239
+		 * handler, which is generally not a good thing to do.
240
+		 */
241
+		return 0;
242
+	}
243
+
244
+	/* Mark stack as inactive */
245
+	pxe_stack->state = CAN_UNLOAD;
246
+	return 1;
247
+}
248
+
249
+/* remove_pxe_stack(): remove PXE stack installed by install_pxe_stack()
250
+ */
251
+void remove_pxe_stack ( void ) {
252
+	/* Ensure stack is deactivated, then free up the memory */
253
+	if ( ensure_pxe_state ( CAN_UNLOAD ) ) {
254
+		forget_base_memory ( pxe_stack, pxe_stack_size );
255
+		pxe_stack = NULL;
256
+	} else {
257
+		printf ( "Cannot remove PXE stack!\n" );
258
+	}
259
+}
260
+
261
+/* xstartpxe(): start up a PXE image
262
+ */
263
+int xstartpxe ( void ) {
264
+	int nbp_exit;
265
+	struct {
266
+		reg16_t bx;
267
+		reg16_t es;
268
+		segoff_t pxe;
269
+	} PACKED in_stack;
270
+	
271
+	/* Set up registers and stack parameters to pass to PXE NBP */
272
+	in_stack.es.word = SEGMENT(&(pxe_stack->pxenv));
273
+	in_stack.bx.word = OFFSET(&(pxe_stack->pxenv));
274
+	in_stack.pxe.segment = SEGMENT(&(pxe_stack->pxe));
275
+	in_stack.pxe.offset = OFFSET(&(pxe_stack->pxe));
276
+
277
+	/* Real-mode trampoline fragment used to jump to PXE NBP
278
+	 */
279
+	RM_FRAGMENT(jump_to_pxe_nbp, 
280
+		"popw %bx\n\t"
281
+		"popw %es\n\t"
282
+		"lcall $" RM_STR(PXE_LOAD_SEGMENT) ", $" RM_STR(PXE_LOAD_OFFSET) "\n\t"
283
+	);
284
+
285
+	/* Call to PXE image */
286
+	gateA20_unset();
287
+	nbp_exit = real_call ( jump_to_pxe_nbp, &in_stack, NULL );
288
+	gateA20_set();
289
+
290
+	return nbp_exit;
291
+}
292
+
293
+int pxe_in_call ( in_call_data_t *in_call_data, va_list params ) {
294
+	/* i386 calling conventions; the only two defined by Intel's
295
+	 * PXE spec.
296
+	 *
297
+	 * Assembly code must pass a long containing the PXE version
298
+	 * code (i.e. 0x201 for !PXE, 0x200 for PXENV+) as the first
299
+	 * parameter after the in_call opcode.  This is used to decide
300
+	 * whether to take parameters from the stack (!PXE) or from
301
+	 * registers (PXENV+).
302
+	 */
303
+	uint32_t api_version = va_arg ( params, typeof(api_version) );
304
+	uint16_t opcode;
305
+	segoff_t segoff;
306
+	t_PXENV_ANY *structure;
307
+		
308
+	if ( api_version >= 0x201 ) {
309
+		/* !PXE calling convention */
310
+		pxe_call_params_t pxe_params
311
+			= va_arg ( params, typeof(pxe_params) );
312
+		opcode = pxe_params.opcode;
313
+		segoff = pxe_params.segoff;
314
+	} else {
315
+		/* PXENV+ calling convention */
316
+		opcode = in_call_data->pm->regs.bx;
317
+		segoff.segment = in_call_data->rm->seg_regs.es;
318
+		segoff.offset = in_call_data->pm->regs.di;
319
+	}
320
+	structure = VIRTUAL ( segoff.segment, segoff.offset );
321
+	return pxe_api_call ( opcode, structure );
322
+}
323
+
324
+#ifdef TEST_EXCLUDE_ALGORITHM
325
+/* This code retained because it's a difficult algorithm to tweak with
326
+ * confidence
327
+ */
328
+int ___test_exclude ( int start, int len, int estart, int elen, int fixbase );
329
+void __test_exclude ( int start, int len, int estart, int elen, int fixbase ) {
330
+	int newrange = ___test_exclude ( start, len, estart, elen, fixbase );
331
+	int newstart = ( newrange >> 16 ) & 0xffff;
332
+	int newlen = ( newrange & 0xffff );
333
+
334
+	printf ( "[%x,%x): excluding [%x,%x) %s gives [%x,%x)\n",
335
+		 start, start + len,
336
+		 estart, estart + elen,
337
+		 ( fixbase == 0 ) ? "  " : "fb",
338
+		 newstart, newstart + newlen );
339
+}
340
+void _test_exclude ( int start, int len, int estart, int elen ) {
341
+	__test_exclude ( start, len, estart, elen, 0 );
342
+	__test_exclude ( start, len, estart, elen, 1 );
343
+}
344
+void test_exclude ( void ) {
345
+	_test_exclude ( 0x8000, 0x1000, 0x0400, 0x200 ); /* before */
346
+	_test_exclude ( 0x8000, 0x1000, 0x9000, 0x200 ); /* after */
347
+	_test_exclude ( 0x8000, 0x1000, 0x7f00, 0x200 ); /* before overlap */
348
+	_test_exclude ( 0x8000, 0x1000, 0x8f00, 0x200 ); /* after overlap */
349
+	_test_exclude ( 0x8000, 0x1000, 0x8000, 0x200 ); /* align start */
350
+	_test_exclude ( 0x8000, 0x1000, 0x8e00, 0x200 ); /* align end */
351
+	_test_exclude ( 0x8000, 0x1000, 0x8100, 0x200 ); /* early overlap */
352
+	_test_exclude ( 0x8000, 0x1000, 0x8d00, 0x200 ); /* late overlap */
353
+	_test_exclude ( 0x8000, 0x1000, 0x7000, 0x3000 ); /* total overlap */
354
+	_test_exclude ( 0x8000, 0x1000, 0x8000, 0x1000 ); /* exact overlap */
355
+}
356
+#endif /* TEST_EXCLUDE_ALGORITHM */
357
+
358
+#else /* PXE_EXPORT */
359
+
360
+/* Define symbols used by the linker scripts, to prevent link errors */
361
+__asm__ ( ".globl _pxe_stack_t_size" );
362
+__asm__ ( ".equ _pxe_stack_t_size, 0" );
363
+
364
+#endif /* PXE_EXPORT */

+ 94
- 0
src/arch/i386/core/pxe_loader.c View File

@@ -0,0 +1,94 @@
1
+/*
2
+ * PXE image loader for Etherboot.
3
+ * 
4
+ * Note: There is no signature check for PXE images because there is
5
+ * no signature.  Well done, Intel!  Consequently, pxe_probe() must be
6
+ * called last of all the image_probe() routines, because it will
7
+ * *always* claim the image.
8
+ */
9
+
10
+#ifndef PXE_EXPORT
11
+#error PXE_IMAGE requires PXE_EXPORT
12
+#endif
13
+
14
+#include "etherboot.h"
15
+#include "pxe_callbacks.h"
16
+#include "pxe_export.h"
17
+#include "pxe.h"
18
+
19
+unsigned long pxe_load_offset;
20
+
21
+static sector_t pxe_download ( unsigned char *data,
22
+			       unsigned int len, int eof );
23
+
24
+static inline os_download_t pxe_probe ( unsigned char *data __unused,
25
+					unsigned int len __unused ) {
26
+	printf("(PXE)");
27
+	pxe_load_offset = 0;
28
+	return pxe_download;
29
+}
30
+
31
+static sector_t pxe_download ( unsigned char *data,
32
+			       unsigned int len, int eof ) {
33
+	unsigned long block_address = PXE_LOAD_ADDRESS + pxe_load_offset;
34
+	PXENV_STATUS_t nbp_exit;
35
+
36
+	/* Check segment will fit.  We can't do this in probe()
37
+	 * because there's nothing in the non-existent header to tell
38
+	 * us how long the image is.
39
+	 */
40
+	if ( ! prep_segment ( block_address, block_address + len, 
41
+			      block_address + len,
42
+			      pxe_load_offset, pxe_load_offset + len ) ) {
43
+		longjmp ( restart_etherboot, -2 );
44
+	}
45
+
46
+	/* Load block into memory, continue loading until eof */
47
+	memcpy ( phys_to_virt ( block_address ), data, len );
48
+	pxe_load_offset += len;
49
+	if ( ! eof ) { 
50
+		return 0;
51
+	}
52
+
53
+	/* Start up PXE NBP */
54
+	done ( 0 );
55
+
56
+	/* Install and activate a PXE stack */
57
+	pxe_stack = install_pxe_stack ( NULL );
58
+	if ( ensure_pxe_state ( READY ) ) {
59
+		/* Invoke the NBP */
60
+		nbp_exit = xstartpxe();
61
+	} else {
62
+		/* Fake success so we tear down the stack */
63
+		nbp_exit = PXENV_STATUS_SUCCESS;
64
+	}
65
+
66
+	/* NBP has three exit codes:
67
+	 *   PXENV_STATUS_KEEP_UNDI : keep UNDI and boot next device
68
+	 *   PXENV_STATUS_KEEP_ALL  : keep all and boot next device
69
+	 *   anything else : remove all and boot next device
70
+	 * 
71
+	 * Strictly, we're meant to hand back to the BIOS, but this
72
+	 * would prevent the useful combination of "PXE NBP fails, so
73
+	 * let Etherboot try to boot its next device".  We therefore
74
+	 * take liberties.
75
+	 */
76
+	if ( nbp_exit != PXENV_STATUS_KEEP_UNDI &&
77
+	     nbp_exit != PXENV_STATUS_KEEP_ALL ) {
78
+		/* Tear down PXE stack */
79
+		remove_pxe_stack();
80
+	}
81
+
82
+	/* Boot next device.  Under strict PXE compliance, exit back
83
+	 * to the BIOS, otherwise let Etherboot move to the next
84
+	 * device.
85
+	 */
86
+#ifdef PXE_STRICT
87
+	longjmp ( restart_etherboot, 255 );
88
+#else
89
+	longjmp ( restart_etherboot, 4 );
90
+#endif
91
+	
92
+	/* Never reached; avoid compiler warning */
93
+	return ( 0 );
94
+}

+ 148
- 0
src/arch/i386/core/realmode.c View File

@@ -0,0 +1,148 @@
1
+/* Real-mode interface: C portions.
2
+ *
3
+ * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
4
+ */
5
+
6
+#include "etherboot.h"
7
+#include "realmode.h"
8
+#include "segoff.h"
9
+
10
+#define RM_STACK_SIZE ( 0x1000 )
11
+
12
+/* gcc won't let us use extended asm outside a function (compiler
13
+ * bug), ao we have to put these asm statements inside a dummy
14
+ * function.
15
+ */
16
+static void work_around_gcc_bug ( void ) __attribute__ ((used));
17
+static void work_around_gcc_bug ( void ) {
18
+	/* Export _real_mode_stack_size as absolute linker symbol */
19
+	__asm__ ( ".globl _real_mode_stack_size" );
20
+	__asm__ ( ".equ _real_mode_stack_size, %c0" : : "i" (RM_STACK_SIZE) );
21
+}
22
+
23
+/* While Etherboot remains in base memory the real-mode stack is
24
+ * placed in the Etherboot main stack.  The first allocation or
25
+ * deallocation of base memory will cause a 'proper' real-mode stack
26
+ * to be allocated.  This will happen before Etherboot is relocated to
27
+ * high memory.
28
+ */
29
+uint32_t real_mode_stack = 0;
30
+size_t real_mode_stack_size = RM_STACK_SIZE;
31
+int lock_real_mode_stack = 0;	/* Set to make stack immobile */
32
+
33
+/* Make a call to a real-mode code block.
34
+ */
35
+
36
+/* These is the structure that exists on the stack as the paramters
37
+ * passed in to _real_call.  We pass a pointer to this struct to
38
+ * prepare_real_call(), to save stack space.
39
+ */
40
+typedef struct {
41
+	void *fragment;
42
+	int fragment_len;
43
+	void *in_stack;
44
+	int in_stack_len;
45
+	void *out_stack;
46
+	int out_stack_len;
47
+} real_call_params_t;
48
+
49
+uint32_t prepare_real_call ( real_call_params_t *p,
50
+			     int local_stack_len, char *local_stack ) {
51
+	char *stack_base;
52
+	char *stack_end;
53
+	char *stack;
54
+	char *s;
55
+	prot_to_real_params_t *p2r_params;
56
+	real_to_prot_params_t *r2p_params;
57
+
58
+	/* Work out where we're putting the stack */
59
+	if ( virt_to_phys(local_stack) < 0xa0000 ) {
60
+		/* Current stack is in base memory.  We can therefore
61
+		 * use it directly, with a constraint on the size that
62
+		 * we don't know; assume that we can use up to
63
+		 * real_mode_stack_size.  (Not a valid assumption, but
64
+		 * it will do).
65
+		 */
66
+		stack_end = local_stack + local_stack_len;
67
+		stack_base = stack_end - real_mode_stack_size;
68
+	} else {
69
+		if (!real_mode_stack) {
70
+			allot_real_mode_stack();
71
+		}
72
+		/* Use the allocated real-mode stack in base memory.
73
+		 * This has fixed start and end points.
74
+		 */
75
+		stack_base = phys_to_virt(real_mode_stack);
76
+		stack_end = stack_base + real_mode_stack_size;
77
+	}
78
+	s = stack = stack_end - local_stack_len;
79
+
80
+	/* Compile input stack and trampoline code to stack */
81
+	if ( p->in_stack_len ) {
82
+		memcpy ( s, p->in_stack, p->in_stack_len );
83
+		s += p->in_stack_len;
84
+	}
85
+	memcpy ( s, _prot_to_real_prefix, prot_to_real_prefix_size );
86
+	s += prot_to_real_prefix_size;
87
+	p2r_params = (prot_to_real_params_t*) ( s - sizeof(*p2r_params) );
88
+	memcpy ( s, p->fragment, p->fragment_len );
89
+	s += p->fragment_len;
90
+	memcpy ( s, _real_to_prot_suffix, real_to_prot_suffix_size );
91
+	s += real_to_prot_suffix_size;
92
+	r2p_params = (real_to_prot_params_t*) ( s - sizeof(*r2p_params) );
93
+
94
+	/* Set parameters within compiled stack */
95
+	p2r_params->ss = p2r_params->cs = SEGMENT ( stack_base );
96
+	p2r_params->esp = virt_to_phys ( stack );
97
+	p2r_params->r2p_params = virt_to_phys ( r2p_params );
98
+	r2p_params->out_stack = ( p->out_stack == NULL ) ?
99
+		0 : virt_to_phys ( p->out_stack );
100
+	r2p_params->out_stack_len = p->out_stack_len;
101
+
102
+	return virt_to_phys ( stack + p->in_stack_len );
103
+}
104
+
105
+
106
+/* Parameters are not genuinely unused; they are passed to
107
+ * prepare_real_call() as part of a real_call_params_t struct.
108
+ */
109
+uint16_t _real_call ( void *fragment, int fragment_len,
110
+		      void *in_stack __unused, int in_stack_len,
111
+		      void *out_stack __unused, int out_stack_len __unused ) {
112
+	uint16_t retval;
113
+
114
+	/* This code is basically equivalent to
115
+	 *
116
+	 *	uint32_t trampoline;
117
+	 *	char local_stack[ in_stack_len + prot_to_real_prefix_size +
118
+	 *			  fragment_len + real_to_prot_suffix_size ];
119
+	 *	trampoline = prepare_real_call ( &fragment, local_stack );
120
+	 *	__asm__ ( "call _virt_to_phys\n\t"
121
+	 *		  "call %%eax\n\t"
122
+	 *		  "call _phys_to_virt\n\t"
123
+	 *		  : "=a" (retval) : "0" (trampoline) );
124
+	 *
125
+	 * but implemented in assembly to avoid problems with not
126
+	 * being certain exactly how gcc handles %esp.
127
+	 */
128
+
129
+	__asm__ ( "pushl %%ebp\n\t"
130
+		  "movl  %%esp, %%ebp\n\t"	/* %esp preserved via %ebp */
131
+		  "subl  %%ecx, %%esp\n\t"	/* space for inline RM stack */
132
+		  "pushl %%esp\n\t"		/* set up RM stack */
133
+		  "pushl %%ecx\n\t"
134
+		  "pushl %%eax\n\t"
135
+		  "call  prepare_real_call\n\t"	/* %eax = trampoline addr */
136
+		  "addl  $12, %%esp\n\t"
137
+		  "call  _virt_to_phys\n\t"	/* switch to phys addr */
138
+		  "call  *%%eax\n\t"		/* call to trampoline */
139
+		  "call  _phys_to_virt\n\t"	/* switch to virt addr */
140
+		  "movl  %%ebp, %%esp\n\t"	/* restore %esp & %ebp */
141
+		  "popl  %%ebp\n\t"
142
+		  : "=a" ( retval )
143
+		  : "0" ( &fragment )
144
+		  , "c" ( ( ( in_stack_len + prot_to_real_prefix_size +
145
+			      fragment_len + real_to_prot_suffix_size )
146
+			    + 0x3 ) & ~0x3 ) );
147
+	return retval;
148
+}

+ 695
- 0
src/arch/i386/core/realmode_asm.S View File

@@ -0,0 +1,695 @@
1
+/* Real-mode interface: assembly-language portions.
2
+ *
3
+ * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
4
+ */
5
+
6
+#include "realmode.h"
7
+#include "callbacks.h"
8
+
9
+#if	1	/* CODE16 */
10
+	
11
+#define BOCHSBP xchgw %bx,%bx
12
+
13
+#define NUM_PUSHA_REGS (8)
14
+#define NUM_SEG_REGS (6)
15
+
16
+	.text
17
+	.arch i386
18
+	.section ".text16.nocompress", "ax", @progbits
19
+	.code16
20
+	
21
+	.equ	CR0_PE,1
22
+
23
+#ifdef	GAS291
24
+#define DATA32 data32;
25
+#define ADDR32 addr32;
26
+#define	LJMPI(x)	ljmp	x
27
+#else
28
+#define DATA32 data32
29
+#define ADDR32 addr32
30
+/* newer GAS295 require #define	LJMPI(x)	ljmp	*x */
31
+#define	LJMPI(x)	ljmp	x
32
+#endif
33
+
34
+/****************************************************************************
35
+ * REAL-MODE CALLBACK INTERFACE
36
+ *
37
+ * This must be copied down to base memory in order for external
38
+ * programs to be able to make calls in to Etherboot.  Store the
39
+ * current physical address of Etherboot (i.e. virt_to_phys(_text)) in
40
+ * (uint32_t)rm_etherboot_location, then copy
41
+ * (uint16_t)rm_callback_interface_size bytes starting at
42
+ * &((void)rm_callback_interface).
43
+ *
44
+ * There are two defined entry points:
45
+ *   Offset RM_IN_CALL     = 0		Near call entry point
46
+ *   Offset RM_IN_CALL_FAR = 2		Far call entry point
47
+ *
48
+ * Note that the routines _prot_to_real and _real_to_prot double as
49
+ * trampoline fragments for external calls (calls from Etherboot to
50
+ * real-mode code).  _prot_to_real does not automatically re-enable
51
+ * interrupts; this is to allow for the potential of using Etherboot
52
+ * code as an ISR.  _real_to_prot does automatically disable
53
+ * interrupts, since we don't have a protected-mode IDT.
54
+ ****************************************************************************
55
+ */
56
+
57
+	.globl	rm_callback_interface
58
+	.code16
59
+rm_callback_interface:
60
+	.globl	_rm_in_call
61
+_rm_in_call:
62
+	jmp	_real_in_call
63
+	.globl	_rm_in_call_far
64
+_rm_in_call_far:
65
+	jmp	_real_in_call_far
66
+
67
+/****************************************************************************
68
+ * _real_in_call
69
+ *
70
+ * Parameters:
71
+ *   16-bit real-mode near/far return address (implicit from [l]call
72
+ *   to routine) Other parameters as for _in_call_far().
73
+ *
74
+ * This routine will convert the 16-bit real-mode far return address
75
+ * to a 32-bit real-mode far return address, switch to protected mode
76
+ * using _real_to_prot and call in to _in_call_far.
77
+ ****************************************************************************
78
+ */
79
+
80
+#define RIC_PRESERVE ( 8 )
81
+#define RIC_OFFSET_CALLADDR ( RIC_PRESERVE )
82
+#define RIC_OFFSET_CALLADDR_E ( RIC_OFFSET_CALLADDR + 4 )
83
+#define RIC_OFFSET_CONTADDR ( RIC_OFFSET_CALLADDR_E )
84
+#define RIC_OFFSET_CONTADDR_E ( RIC_OFFSET_CONTADDR + 4 )
85
+#define RIC_OFFSET_OPCODE ( RIC_OFFSET_CONTADDR_E )
86
+#define RIC_OFFSET_OPCODE_E ( RIC_OFFSET_OPCODE + 4 )
87
+#define RIC_OFFSET_SEG_REGS ( RIC_OFFSET_OPCODE_E )
88
+#define RIC_OFFSET_SEG_REGS_E ( RIC_OFFSET_SEG_REGS + ( NUM_SEG_REGS * 2 ) )
89
+#define RIC_OFFSET_PAD ( RIC_OFFSET_SEG_REGS_E )
90
+#define RIC_OFFSET_PAD_E ( RIC_OFFSET_PAD + 2 )
91
+#define RIC_OFFSET_FLAGS ( RIC_OFFSET_PAD_E )
92
+#define RIC_OFFSET_FLAGS_E ( RIC_OFFSET_FLAGS + 2 )
93
+#define RIC_OFFSET_RETADDR ( RIC_OFFSET_FLAGS_E )
94
+#define RIC_OFFSET_RETADDR_E ( RIC_OFFSET_RETADDR + 4 )
95
+#define RIC_OFFSET_ORIG_OPCODE ( RIC_OFFSET_RETADDR_E )
96
+#define RIC_INSERT_LENGTH ( RIC_OFFSET_OPCODE_E - RIC_OFFSET_CALLADDR )
97
+	
98
+	.code16
99
+_real_in_call:
100
+	/* Expand near return address to far return address
101
+	 */
102
+	pushw	%ax		/* Extend stack, store %ax */
103
+	pushfw
104
+	pushw	%bp
105
+	movw	%sp, %bp
106
+	movw	%cs, %ax
107
+	xchgw	%ax, 6(%bp)
108
+	xchgw	%ax, 4(%bp)	/* also restores %ax */
109
+	popw	%bp
110
+	popfw
111
+	/* Fall through to _real_in_call_far */
112
+	
113
+_real_in_call_far:
114
+	/* Store flags and pad */
115
+	pushfw
116
+	pushw	%ax
117
+
118
+	/* Store segment registers.  Order matches that of seg_regs_t */
119
+	pushw	%gs
120
+	pushw	%fs
121
+	pushw	%es
122
+	pushw	%ds
123
+	pushw	%ss
124
+	pushw	%cs
125
+
126
+	/* Switch to protected mode */
127
+	call _real_to_prot
128
+	.code32
129
+
130
+	/* Allow space for expanded stack */
131
+	subl	$RIC_INSERT_LENGTH, %esp
132
+	
133
+	/* Store temporary registers */
134
+	pushl	%ebp
135
+	pushl	%eax
136
+
137
+	/* Copy opcode, set EB_CALL_FROM_REAL_MODE and EP_SKIP_OPCODE.
138
+	 * Copy it because _in_call() and i386_in_call() expect it at
139
+	 * a fixed position, not as part of the va_list.
140
+	 */
141
+	movl	RIC_OFFSET_ORIG_OPCODE(%esp), %eax
142
+	orl	$(EB_CALL_FROM_REAL_MODE|EB_SKIP_OPCODE), %eax
143
+	movl	%eax, RIC_OFFSET_OPCODE(%esp)
144
+	
145
+	/* Set up call and return addresses */
146
+	call	1f
147
+1:	popl	%ebp
148
+	subl	$1b, %ebp			/* %ebp = offset */
149
+	movl	rm_etherboot_location(%ebp), %eax  /* Etherboot phys addr */
150
+	subl	$_text, %eax
151
+	addl	$_in_call, %eax			/* _in_call phys addr */
152
+	movl	%eax, RIC_OFFSET_CALLADDR(%esp)
153
+	leal	2f(%ebp), %eax			/* continuation address */
154
+	movl	%eax, RIC_OFFSET_CONTADDR(%esp)
155
+	
156
+	/* Restore temporary registers */
157
+	popl	%eax
158
+	popl	%ebp
159
+
160
+	/* Call to _in_call */
161
+	ret
162
+	/* opcode will be popped automatically thanks to EB_SKIP_OPCODE */
163
+
164
+2:	/* Continuation point */
165
+	call	_prot_to_real			/* Return to real mode */
166
+	/* Note: the first two words of our segment register store
167
+	 * happens to be exactly what we need to pass as parameters to
168
+	 * _prot_to_real.
169
+	 */
170
+	.code16
171
+	popw	%ds				/* Restore segment registers */
172
+	popw	%ds				/* (skip cs&ss since these   */
173
+	popw	%ds				/* have already been set by  */
174
+	popw	%es				/* _prot_to_real	     */
175
+	popw	%fs
176
+	popw	%gs
177
+	addw	$2, %sp				/* skip pad */
178
+
179
+	/* Check for EB_SKIP_OPCODE */
180
+	pushw	%bp
181
+	movw	%sp, %bp
182
+	testl	$EB_SKIP_OPCODE, 6(%bp)
183
+	popw	%bp
184
+	jnz	1f
185
+	/* Normal return */
186
+	popfw					/* Restore interrupt status */
187
+	lret					/* Back to caller */
188
+1:	/* Return and skip opcode */
189
+	popfw
190
+	lret	$4
191
+
192
+/****************************************************************************
193
+ * rm_etherboot_location: the current physical location of Etherboot.
194
+ * Needed so that real-mode callback routines can locate Etherboot.
195
+ ****************************************************************************
196
+ */
197
+	.globl rm_etherboot_location
198
+rm_etherboot_location:	.long 0
199
+		
200
+/****************************************************************************
201
+ * _prot_to_real_prefix
202
+ *
203
+ * Trampoline fragment.  Switch from 32-bit protected mode with flat
204
+ * physical addresses to 16-bit real mode.  Store registers in the
205
+ * trampoline for restoration by _real_to_prot_suffix.  Switch to
206
+ * stack in base memory.
207
+ ****************************************************************************
208
+ */
209
+	
210
+	.globl _prot_to_real_prefix
211
+	.code32
212
+_prot_to_real_prefix:
213
+	/* Registers to preserve */
214
+	pushl	%ebx
215
+	pushl	%esi
216
+	pushl	%edi
217
+	pushl	%ebp
218
+
219
+	/* Calculate offset */
220
+	call	1f
221
+1:	popl	%ebp
222
+	subl	$1b, %ebp		/* %ebp = offset for labels in p2r*/
223
+
224
+	/* Preserve registers and return address in r2p_params */
225
+	movl	p2r_r2p_params(%ebp), %ebx
226
+	subl	$r2p_params, %ebx	/* %ebx = offset for labels in r2p */
227
+	popl	r2p_ebp(%ebx)
228
+	popl	r2p_edi(%ebx)
229
+	popl	r2p_esi(%ebx)
230
+	popl	r2p_ebx(%ebx)
231
+	popl	r2p_ret_addr(%ebx)
232
+	movl	%esp, r2p_esp(%ebx)
233
+
234
+	/* Switch stacks */
235
+	movl	p2r_esp(%ebp), %esp
236
+
237
+	/* Switch to real mode */
238
+	pushl	p2r_segments(%ebp)
239
+	call	_prot_to_real
240
+	.code16
241
+	addw	$4, %sp
242
+		
243
+	/* Fall through to next trampoline fragment */
244
+	jmp	_prot_to_real_prefix_end
245
+	
246
+/****************************************************************************
247
+ * _prot_to_real
248
+ *
249
+ * Switch from 32-bit protected mode with flat physical addresses to
250
+ * 16-bit real mode.  Stack and code must be in base memory when
251
+ * called.  %cs, %ss, %eip, %esp are changed to real-mode values,
252
+ * other segment registers are destroyed, all other registers are
253
+ * preserved.  Interrupts are *not* enabled.
254
+ *
255
+ * Parameters:
256
+ *   %cs		Real-mode code segment (word)
257
+ *   %ss		Real-mode stack segment (word)
258
+ ****************************************************************************
259
+ */
260
+
261
+#define P2R_PRESERVE ( 12 )
262
+#define P2R_OFFSET_RETADDR ( P2R_PRESERVE )
263
+#define P2R_OFFSET_RETADDR_E ( P2R_OFFSET_RETADDR + 4 )
264
+#define P2R_OFFSET_CS ( P2R_OFFSET_RETADDR_E )
265
+#define P2R_OFFSET_CS_E ( P2R_OFFSET_CS + 2 )
266
+#define P2R_OFFSET_SS ( P2R_OFFSET_CS_E )
267
+#define P2R_OFFSET_SS_E ( P2R_OFFSET_SS + 2 )
268
+
269
+	.globl _prot_to_real
270
+	.code32
271
+_prot_to_real:
272
+	/* Preserve registers */
273
+	pushl	%ebp
274
+	pushl	%ebx
275
+	pushl	%eax
276
+	
277
+	/* Calculate offset */
278
+	call	1f
279
+1:	popl	%ebp
280
+	subl	$1b, %ebp		/* %ebp = offset for labels in p2r*/
281
+
282
+	/* Set up GDT with real-mode limits and appropriate bases for
283
+	 * real-mode %cs and %ss.  Set up protected-mode continuation
284
+	 * point on stack.
285
+	 */
286
+	/* Fixup GDT */
287
+	leal	p2r_gdt(%ebp), %eax
288
+	movl	%eax, p2r_gdt_addr(%ebp)
289
+
290
+	/* Calculate CS base address: set GDT code segment, adjust
291
+	 * return address, set up continuation address on stack.
292
+	 */
293
+	movzwl	P2R_OFFSET_CS(%esp), %eax
294
+	shll	$4, %eax
295
+	/* Change return address to real-mode far address */
296
+	subl	%eax, P2R_OFFSET_RETADDR(%esp)
297
+	movl	%eax, %ebx
298
+	shrl	$4, %ebx
299
+	movw	%bx, (P2R_OFFSET_RETADDR+2)(%esp)
300
+	/* First real mode address */
301
+	movl	%eax, %ebx
302
+	shrl	$4, %ebx
303
+	pushw	%bx
304
+	leal	3f(%ebp), %ebx
305
+	subl	%eax, %ebx
306
+	pushw	%bx
307
+	/* Continuation address */
308
+	pushl	$(p2r_rmcs - p2r_gdt)
309
+	leal	2f(%ebp), %ebx
310
+	subl	%eax, %ebx
311
+	pushl	%ebx
312
+	/* Code segment in GDT */
313
+	movw	%ax, (p2r_rmcs+2)(%ebp)
314
+	shrl	$16, %eax			/* Remainder of cs base addr */
315
+	movb	%al, (p2r_rmcs+4)(%ebp)
316
+	movb	%ah, (p2r_rmcs+7)(%ebp)
317
+
318
+	/* Calculate SS base address: set GDT data segment, retain to
319
+	 * use for adjusting %esp.
320
+	 */
321
+	movzwl	(12+P2R_OFFSET_SS)(%esp), %eax	/* Set ss base address */
322
+	shll	$4, %eax
323
+	movw	%ax, (p2r_rmds+2)(%ebp)
324
+	movl	%eax, %ebx
325
+	shrl	$16, %ebx
326
+	movb	%bl, (p2r_rmds+4)(%ebp)
327
+	movb	%bh, (p2r_rmds+7)(%ebp)
328
+
329
+	/* Load GDT */
330
+	lgdt	p2r_gdt(%ebp)
331
+	/* Reload all segment registers and adjust %esp */
332
+	movw	$(p2r_rmds - p2r_gdt), %bx /* Pmode DS */
333
+	movw	%bx, %ss
334
+	subl	%eax, %esp		/* %esp now less than 0x10000 */
335
+	movw	%bx, %ds
336
+	movw	%bx, %es
337
+	movw	%bx, %fs
338
+	movw	%bx, %gs
339
+	lret				/* %cs:eip */
340
+2:	/* Segment registers now have 16-bit limits. */
341
+	.code16
342
+
343
+	/* Switch to real mode */
344
+	movl	%cr0, %ebx
345
+	andb	$0!CR0_PE, %bl
346
+	movl	%ebx, %cr0
347
+
348
+	/* Make intersegment jmp to flush the processor pipeline
349
+	 * and reload %cs:%eip (to clear upper 16 bits of %eip).
350
+	 */
351
+	lret
352
+3:		
353
+	
354
+	/* Load real-mode segment value to %ss.  %sp already OK */
355
+	shrl	$4, %eax
356
+	movw	%ax, %ss
357
+
358
+	/* Restore registers */
359
+	popl	%eax
360
+	popl	%ebx
361
+	popl	%ebp
362
+
363
+	/* Return to caller in real-mode */
364
+	lret
365
+
366
+#ifdef FLATTEN_REAL_MODE
367
+#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x8f
368
+#else
369
+#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
370
+#endif
371
+
372
+p2r_gdt:
373
+p2r_gdtarg:
374
+p2r_gdt_limit:		.word p2r_gdt_end - p2r_gdt - 1
375
+p2r_gdt_addr:		.long 0
376
+p2r_gdt_padding:	.word 0
377
+p2r_rmcs:
378
+	/* 16 bit real mode code segment */
379
+	.word	0xffff,(0&0xffff)
380
+	.byte	(0>>16),0x9b,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
381
+p2r_rmds:
382
+	/* 16 bit real mode data segment */
383
+	.word	0xffff,(0&0xffff)
384
+	.byte	(0>>16),0x93,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
385
+p2r_gdt_end:
386
+
387
+	/* This is the end of the trampoline prefix code.  When used
388
+	 * as a prefix, fall through to the following code in the
389
+	 * trampoline.
390
+	 */
391
+p2r_params: /* Structure must match prot_to_real_params_t in realmode.h */
392
+p2r_esp:	.long 0
393
+p2r_segments:
394
+p2r_cs:		.word 0
395
+p2r_ss:		.word 0
396
+p2r_r2p_params:	.long 0
397
+	.globl	_prot_to_real_prefix_end
398
+_prot_to_real_prefix_end:
399
+	
400
+	.globl	_prot_to_real_prefix_size
401
+	.equ	_prot_to_real_prefix_size, _prot_to_real_prefix_end - _prot_to_real_prefix
402
+	.globl	prot_to_real_prefix_size
403
+prot_to_real_prefix_size:	
404
+	.word	_prot_to_real_prefix_size
405
+	
406
+/****************************************************************************
407
+ * _real_to_prot_suffix
408
+ *
409
+ * Trampoline fragment.  Switch from 16-bit real-mode to 32-bit
410
+ * protected mode with flat physical addresses.  Copy returned stack
411
+ * parameters to output_stack.  Restore registers preserved by
412
+ * _prot_to_real_prefix.  Restore stack to previous location.
413
+ ****************************************************************************
414
+ */
415
+
416
+	.globl _real_to_prot_suffix
417
+	.code16
418
+_real_to_prot_suffix:
419
+
420
+	/* Switch to protected mode */
421
+	call	_real_to_prot
422
+	.code32
423
+
424
+	/* Calculate offset */
425
+	call	1f
426
+1:	popl	%ebp
427
+	subl	$1b, %ebp		/* %ebp = offset for labels in r2p */
428
+
429
+	/* Copy stack to out_stack */
430
+	movl	r2p_out_stack(%ebp), %edi
431
+	movl	r2p_out_stack_len(%ebp), %ecx
432
+	movl	%esp, %esi
433
+	cld
434
+	rep movsb
435
+
436
+	/* Switch back to original stack */
437
+	movl	r2p_esp(%ebp), %esp
438
+
439
+	/* Restore registers and return */
440
+	pushl	r2p_ret_addr(%ebp)	/* Set up return address on stack */
441
+	movl	r2p_ebx(%ebp), %ebx
442
+	movl	r2p_esi(%ebp), %esi
443
+	movl	r2p_edi(%ebp), %edi
444
+	movl	r2p_ebp(%ebp), %ebp
445
+	ret
446
+
447
+/****************************************************************************
448
+ * _real_to_prot
449
+ *
450
+ * Switch from 16-bit real-mode to 32-bit protected mode with flat
451
+ * physical addresses.  All segment registers are destroyed, %eip and
452
+ * %esp are changed to flat physical values, all other registers are
453
+ * preserved.  Interrupts are disabled.
454
+ *
455
+ * Parameters: none
456
+ ****************************************************************************
457
+ */
458
+
459
+#define R2P_PRESERVE ( 12 )
460
+#define R2P_OFFSET_RETADDR ( R2P_PRESERVE )
461
+#define R2P_OFFSET_ORIG_RETADDR ( R2P_OFFSET_RETADDR + 2 )
462
+
463
+	.globl _real_to_prot
464
+	.code16		
465
+_real_to_prot:
466
+	/* Disable interrupts */
467
+	cli
468
+	/* zero extend the return address */
469
+	pushw	$0
470
+
471
+	/* Preserve registers */
472
+	pushl	%ebp
473
+	pushl	%ebx
474
+	pushl	%eax
475
+
476
+	/* Convert 16-bit real-mode near return address to
477
+	 * 32-bit pmode physical near return address
478
+	 */
479
+	movw	%sp, %bp
480
+	xorl	%ebx, %ebx
481
+	push	%cs
482
+	popw	%bx
483
+	movw	%bx, %ds
484
+	shll	$4, %ebx
485
+	movzwl	%ss:R2P_OFFSET_ORIG_RETADDR(%bp), %eax
486
+	addl	%ebx, %eax
487
+	movl	%eax, %ss:(R2P_OFFSET_RETADDR)(%bp)
488
+
489
+	/* Store the code segment physical base address in %ebp */
490
+	movl	%ebx, %ebp
491
+
492
+	/* Find the offset within the code segment that I am running at */
493
+	xorl	%ebx, %ebx
494
+	call	1f
495
+1:	popw	%bx
496
+
497
+	/* Set up GDT */
498
+	leal	(r2p_gdt-1b)(%bx), %eax	/* %ds:ebx = %ds:bx = &(r2p_gdt) */
499
+	addl	%ebp, %eax		/* %eax = &r2p_gdt (physical) */
500
+	movl	%eax, %ds:(r2p_gdt-1b+2)(%bx) /* Set phys. addr. in r2p_gdt */
501
+
502
+	/* Compute the first protected mode physical address */
503
+	leal	(2f-1b)(%bx), %eax
504
+	addl	%ebp, %eax
505
+	movl	%eax, %ds:(r2p_paddr-1b)(%bx)
506
+
507
+	/* Calculate new %esp */
508
+	xorl	%eax, %eax
509
+	push	%ss
510
+	popw	%ax
511
+	shll	$4, %eax
512
+	movzwl	%sp, %ebp
513
+	addl	%eax, %ebp		/* %ebp = new %esp */
514
+	
515
+	/* Load GDT */
516
+	DATA32 lgdt %ds:(r2p_gdt-1b)(%bx)	/* Load GDT */
517
+
518
+	/* Switch to protected mode */
519
+	movl	%cr0, %eax
520
+	orb	$CR0_PE, %al
521
+	movl	%eax, %cr0
522
+
523
+	/* flush prefetch queue, and reload %cs:%eip */
524
+	DATA32 ljmp %ds:(r2p_paddr-1b)(%bx)
525
+	.code32
526
+2:
527
+	
528
+	/* Load segment registers, adjust %esp */
529
+	movw	$(r2p_pmds-r2p_gdt), %ax
530
+	movw	%ax, %ss
531
+	movl	%ebp, %esp
532
+	movw	%ax, %ds
533
+	movw	%ax, %es
534
+	movw	%ax, %fs
535
+	movw	%ax, %gs
536
+
537
+	/* Restore registers */
538
+	popl	%eax
539
+	popl	%ebx
540
+	popl	%ebp
541
+
542
+	/* return to caller */
543
+	ret
544
+
545
+r2p_gdt:
546
+	.word	r2p_gdt_end - r2p_gdt - 1	/* limit */
547
+	.long 0					/* addr */
548
+	.word 0
549
+r2p_pmcs:
550
+	/* 32 bit protected mode code segment, physical addresses */
551
+	.word	0xffff, 0
552
+	.byte	0, 0x9f, 0xcf, 0
553
+r2p_pmds:
554
+	/* 32 bit protected mode data segment, physical addresses */
555
+	.word	0xffff,0
556
+	.byte	0,0x93,0xcf,0
557
+r2p_gdt_end:
558
+
559
+r2p_paddr:
560
+	.long 2b
561
+	.word r2p_pmcs - r2p_gdt, 0
562
+
563
+
564
+	/* This is the end of the trampoline suffix code.
565
+	 */
566
+r2p_params: /* Structure must match real_to_prot_params_t in realmode.h */
567
+r2p_ret_addr:		.long 0
568
+r2p_esp:		.long 0
569
+r2p_ebx:		.long 0
570
+r2p_esi:		.long 0
571
+r2p_edi:		.long 0
572
+r2p_ebp:		.long 0
573
+r2p_out_stack:		.long 0
574
+r2p_out_stack_len:	.long 0
575
+	.globl	_real_to_prot_suffix_end
576
+_real_to_prot_suffix_end:
577
+
578
+	.globl	_real_to_prot_suffix_size
579
+	.equ	_real_to_prot_suffix_size, _real_to_prot_suffix_end - _real_to_prot_suffix
580
+	.globl	real_to_prot_suffix_size
581
+real_to_prot_suffix_size:
582
+	.word	_real_to_prot_suffix_size
583
+
584
+rm_callback_interface_end:
585
+
586
+	.globl	_rm_callback_interface_size
587
+	.equ	_rm_callback_interface_size, rm_callback_interface_end - rm_callback_interface
588
+	.globl	rm_callback_interface_size
589
+rm_callback_interface_size:
590
+	.word	_rm_callback_interface_size
591
+
592
+/****************************************************************************
593
+ * END OF REAL-MODE CALLBACK INTERFACE
594
+ ****************************************************************************
595
+ */
596
+
597
+
598
+#ifdef PXE_EXPORT
599
+/****************************************************************************
600
+ * PXE CALLBACK INTERFACE
601
+ *
602
+ * Prepend this to rm_callback_interface to create a real-mode PXE
603
+ * callback interface.
604
+ ****************************************************************************
605
+ */
606
+	.section ".text16", "ax", @progbits
607
+	.globl	pxe_callback_interface
608
+	.code16
609
+pxe_callback_interface:
610
+
611
+/* Macro to calculate offset of labels within code segment in
612
+ * installed copy of code.
613
+ */
614
+#define INSTALLED(x) ( (x) - pxe_callback_interface )
615
+
616
+/****************************************************************************
617
+ * PXE entry points (!PXE and PXENV+ APIs)
618
+ ****************************************************************************
619
+ */
620
+	/* in_call mechanism for !PXE API calls */
621
+	.globl	_pxe_in_call_far
622
+_pxe_in_call_far:
623
+	/* Prepend "PXE API call" and "API version 0x201" to stack */
624
+	pushl	$0x201
625
+	jmp	1f
626
+	/* in_call mechanism for PXENV+ API calls */
627
+	.globl	_pxenv_in_call_far
628
+_pxenv_in_call_far:
629
+	/* Prepend "PXE API call" and "API version 0x200" to stack */
630
+	pushl	$0x200
631
+1:	pushl	$EB_OPCODE_PXE
632
+	/* Perform real-mode in_call */
633
+	call	pxe_rm_in_call
634
+	/* Return */
635
+	addw	$8, %sp
636
+	lret
637
+
638
+/****************************************************************************
639
+ * PXE installation check (INT 1A) code
640
+ ****************************************************************************
641
+ */
642
+	.globl	_pxe_intercept_int1a
643
+_pxe_intercept_int1a:
644
+	pushfw
645
+	cmpw	$0x5650, %ax
646
+	jne	2f
647
+1:	/* INT 1A,5650 - Intercept */
648
+	popfw
649
+	/* Set up return values according to PXE spec: */
650
+	movw	$0x564e, %ax		/* AX := 564Eh (VN) */
651
+	pushw	%cs:INSTALLED(_pxe_pxenv_segment)
652
+	popw	%es			/* ES:BX := &(PXENV+ structure) */
653
+	movw	%cs:INSTALLED(_pxe_pxenv_offset), %bx
654
+	clc				/* CF is cleared */
655
+	lret	$2			/* 'iret' without reloading flags */
656
+2:	/* INT 1A,other - Do not intercept */
657
+	popfw
658
+	ljmp	%cs:*INSTALLED(_pxe_intercepted_int1a)
659
+
660
+	.globl	_pxe_intercepted_int1a
661
+_pxe_intercepted_int1a:	.word 0,0
662
+	.globl	_pxe_pxenv_location
663
+_pxe_pxenv_location:
664
+_pxe_pxenv_offset:	.word 0
665
+_pxe_pxenv_segment:	.word 0
666
+	
667
+pxe_rm_in_call:	
668
+pxe_attach_rm:
669
+	/* rm_callback_interface must be appended here */
670
+
671
+pxe_callback_interface_end:
672
+
673
+	.globl	_pxe_callback_interface_size
674
+	.equ	_pxe_callback_interface_size, pxe_callback_interface_end - pxe_callback_interface
675
+	.globl	pxe_callback_interface_size
676
+pxe_callback_interface_size:
677
+	.word	_pxe_callback_interface_size
678
+
679
+#else	/* PXE_EXPORT */
680
+	
681
+/* Define symbols used by the linker scripts, to prevent link errors */
682
+	.globl	_pxe_callback_interface_size
683
+	.equ	_pxe_callback_interface_size, 0	
684
+	
685
+#endif	/* PXE_EXPORT */
686
+
687
+#else	/* CODE16 */
688
+
689
+/* Define symbols used by the linker scripts, to prevent link errors */
690
+	.globl	_rm_callback_interface_size
691
+	.equ	_rm_callback_interface_size, 0	
692
+	.globl	_pxe_callback_interface_size
693
+	.equ	_pxe_callback_interface_size, 0	
694
+		
695
+#endif	/* CODE16 */

+ 285
- 0
src/arch/i386/core/start16.S View File

@@ -0,0 +1,285 @@
1
+/*****************************************************************************
2
+ *
3
+ * THIS FILE IS NOW OBSOLETE.
4
+ *
5
+ * The functions of this file are now placed in init.S.
6
+ *
7
+ *****************************************************************************
8
+ */
9
+	
10
+#ifndef PCBIOS
11
+#error	"16bit code is only supported with the PCBIOS"
12
+#endif
13
+
14
+#define	CODE_SEG 0x08
15
+#define DATA_SEG 0x10
16
+
17
+#define EXEC_IN_SITU_MAGIC	0x45524548	/* 'HERE' */
18
+
19
+	.equ CR0_PE, 1
20
+
21
+#ifdef	GAS291
22
+#define DATA32 data32;
23
+#define ADDR32 addr32;
24
+#define	LJMPI(x)	ljmp	x
25
+#else
26
+#define DATA32 data32
27
+#define ADDR32 addr32
28
+/* newer GAS295 require #define	LJMPI(x)	ljmp	*x */
29
+#define	LJMPI(x)	ljmp	x
30
+#endif
31
+
32
+/*****************************************************************************
33
+ *
34
+ * start16 : move payload to desired area of memory, set up for exit
35
+ *	     back to prefix, set up for 32-bit code.
36
+ *
37
+ * Enter (from prefix) with es:di = 0x4552:0x4548 if you want to
38
+ * prevent start16 from moving the payload.  There are three
39
+ * motivations for moving the payload:
40
+ * 
41
+ * 1. It may be in ROM, in which case we need to move it to RAM.
42
+ * 2. Whatever loaded us probably didn't know about our memory usage
43
+ *    beyond the end of the image file.  We should claim this memory
44
+ *    before using it.
45
+ *
46
+ * Unless the prefix instructs us otherwise we will move the payload to:
47
+ *
48
+ *    An area of memory claimed from the BIOS via 40:13.
49
+ *
50
+ * We use the main Etherboot stack (within the image target) as our
51
+ * stack; we don't rely on the prefix passing us a stack usable for
52
+ * anything other than the prefix's return address.  The (first 512
53
+ * bytes of the) prefix code segment is copied to a safe archive
54
+ * location.
55
+ *
56
+ * When we return to the prefix (from start32), we copy this code back
57
+ * to a new area of memory, restore the prefix's ss:sp and ljmp back
58
+ * to the copy of the prefix.  The prefix will see a return from
59
+ * start16 *but* may be executing at a new location.  Code following
60
+ * the lcall to start16 must therefore be position-independent and
61
+ * must also be within [cs:0000,cs:01ff].  We make absolutely no
62
+ * guarantees about the stack contents when the prefix regains
63
+ * control.
64
+ * 
65
+ * Trashes just about all registers, including all the segment
66
+ * registers.
67
+ *
68
+ *****************************************************************************
69
+ */
70
+
71
+	.text
72
+	.code16
73
+	.arch i386
74
+	.org 0
75
+	.globl _start16
76
+_start16:
77
+
78
+/*****************************************************************************
79
+ * Work out where we are going to place our image (image = optional
80
+ * decompressor + runtime).  Exit this stage with %ax containing the
81
+ * runtime target address divided by 16 (i.e. a real-mode segment
82
+ * address).
83
+ *****************************************************************************
84
+ */	
85
+	movw	%es, %ax
86
+	cmpw	$(EXEC_IN_SITU_MAGIC >> 16), %ax
87
+	jne	exec_moved
88
+	cmpw	$(EXEC_IN_SITU_MAGIC & 0xffff), %di
89
+	jne	exec_moved
90
+exec_in_situ: 
91
+	/* Prefix has warned us not to move the payload.  Simply
92
+	 * calculate where the image is going to end up, so we can
93
+	 * work out where to put our stack.
94
+	 */
95
+	movw	%cs, %ax
96
+	addw	$((payload-_start16)/16), %ax
97
+	jmp	99f
98
+exec_moved:
99
+	/* Claim an area of base memory from the BIOS and put the
100
+	 * payload there.  arch_relocated_to() will deal with freeing
101
+	 * up this memory once we've relocated to high memory.
102
+	 */
103
+	movw	$0x40, %ax
104
+	movw	%ax, %es
105
+	movw	%es:(0x13), %ax		/* FBMS in kb to %ax */
106
+	shlw	$6, %ax			/* ... in paragraphs */
107
+	subw	$__image_size_pgh, %ax	/* Subtract space for image */
108
+	shrw	$6, %ax			/* Round down to nearest kb */
109
+	movw	%ax, %es:(0x13)		/* ...and claim memory from BIOS */
110
+	shlw	$6, %ax
111
+99:
112
+	/* At this point %ax contains the segment address for the
113
+	 * start of the image (image = optional decompressor + runtime).
114
+	 */
115
+
116
+/*****************************************************************************
117
+ * Set up stack in start32's stack space within the place we're going
118
+ * to copy Etherboot to, reserve space for GDT, copy return address
119
+ * from prefix stack, store prefix stack address
120
+ *****************************************************************************
121
+ */
122
+	popl	%esi			/* Return address */
123
+	mov	%ss, %bx		/* %es:di = prefix stack address   */
124
+	mov	%bx, %es		/* (*after* pop of return address) */
125
+	movw	%sp, %di
126
+	movw	$__offset_stack_pgh, %bx	/* Set up Etherboot stack */
127
+	addw	%ax, %bx
128
+	movw	%bx, %ss
129
+	movw	$__stack_size, %sp
130
+	subw	$(_gdt_end - _gdt), %sp	/* Reserve space for GDT */
131
+	movw	%sp, %bp		/* Record GDT location */	
132
+	/* Set up i386_rm_in_call_data_t structure on stack.  This is
133
+	 * the same structure as is set up by rm_in_call.
134
+	 */
135
+	pushl	$0			/* Dummy opcode */
136
+	pushl	%esi			/* Prefix return address */
137
+	pushfw				/* Flags */
138
+	pushw	%di			/* Prefix %sp */
139
+	pushw	%gs			/* Segment registers */
140
+	pushw	%fs
141
+	pushw	%es
142
+	pushw	%ds
143
+	pushw	%es			/* Prefix %ss */
144
+	pushw	%cs
145
+	/* Stack is now 32-bit aligned */
146
+	
147
+	/* %ax still contains image target segment address */
148
+
149
+/*****************************************************************************
150
+ * Calculate image target and prefix code physical addresses, store on stack
151
+ * for use in copy routine.
152
+ *****************************************************************************
153
+ */
154
+	movzwl	%es:-2(%di), %ebx	/* Prefix code segment */
155
+	shll	$4, %ebx
156
+	pushl	%ebx			/* Prefix code physical address */
157
+	movzwl	%ax, %edi		/* Image target segment */
158
+	shll	$4, %edi
159
+	pushl	%edi			/* Image target physical address */
160
+
161
+/*****************************************************************************
162
+ * Transition to 32-bit protected mode.  Set up all segment
163
+ * descriptors to use flat physical addresses.
164
+ *****************************************************************************
165
+ */
166
+	/* Copy gdt to area reserved on stack
167
+	 */
168
+	push	%cs			/* GDT source location -> %ds:%si */
169
+	pop	%ds
170
+	mov	$(_gdt - _start16), %si
171
+	push	%ss			/* GDT target location -> %es:%di */
172
+	pop	%es
173
+	mov	%bp, %di
174
+	mov	$(_gdt_end - _gdt), %cx
175
+	cld
176
+	rep movsb			/* Copy GDT to stack */
177
+	movl	%ss, %eax
178
+	shll	$4, %eax
179
+	movzwl	%bp, %ebx
180
+	addl	%eax, %ebx		/* Physical addr of GDT copy -> %ebx */
181
+	movl	%ebx, 2(%bp)		/* Fill in addr field in GDT */
182
+		
183
+	/* Compute the offset I am running at.
184
+	 */
185
+	movl	%cs, %ebx 
186
+	shll	$4, %ebx		/* %ebx = offset for start16 symbols */
187
+
188
+	/* Switch to 32bit protected mode.
189
+	 */
190
+	cli				/* Disable interrupts */
191
+	lgdt	(%bp)			/* Load GDT from stack */
192
+	movl	%cr0, %eax		/* Set protected mode bit */
193
+	orb	$CR0_PE, %al
194
+	movl	%eax, %cr0
195
+	movl	%ss, %eax		/* Convert stack pointer to 32bit */
196
+	shll	$4, %eax
197
+	movzwl	%sp, %esp
198
+	addl	%eax, %esp
199
+	movl	$DATA_SEG, %eax		/* Reload the segment registers */
200
+	movl	%eax, %ds
201
+	movl	%eax, %es
202
+	movl	%eax, %ss
203
+	movl	%eax, %fs
204
+	movl	%eax, %gs
205
+	/* Flush prefetch queue, and reload %cs:%eip by effectively ljmping
206
+	 * to code32_start.  Do the jump via pushl and lret because the text
207
+	 * may not be writable/
208
+	 */
209
+	pushl	$CODE_SEG
210
+	ADDR32 leal (code32_start-_start16)(%ebx), %eax
211
+	pushl	%eax	
212
+	DATA32 lret /* DATA32 needed, because we're still in 16-bit mode */
213
+
214
+_gdt:
215
+gdtarg:
216
+	.word	_gdt_end - _gdt - 1	/* limit */
217
+	.long 0				/* addr */
218
+	.word 0
219
+_pmcs:
220
+	/* 32 bit protected mode code segment */
221
+	.word	0xffff, 0
222
+	.byte	0, 0x9f, 0xcf, 0
223
+_pmds:
224
+	/* 32 bit protected mode data segment */
225
+	.word	0xffff,0
226
+	.byte	0,0x93,0xcf,0
227
+_gdt_end:
228
+
229
+	.code32
230
+code32_start:	
231
+	
232
+/*****************************************************************************
233
+ * Copy payload to target location.  Do the copy backwards, since if
234
+ * there's overlap with a forward copy then it means start16 is going
235
+ * to get trashed during the copy anyway...
236
+ *****************************************************************************
237
+ */
238
+	popl	%edi		/* Image target physical address */
239
+	pushl	%edi
240
+	leal	(payload-_start16)(%ebx), %esi /* Image source physical addr */
241
+	movl	$__payload_size, %ecx /* Payload size (not image size) */
242
+	addl	%ecx, %edi	/* Start at last byte (length - 1) */
243
+	decl	%edi
244
+	addl	%ecx, %esi
245
+	decl	%esi
246
+	std			/* Backward copy of image */
247
+	rep movsb
248
+	cld
249
+	popl	%edi		/* Restore image target physical address */
250
+	leal	__decompressor_uncompressed(%edi), %ebx
251
+	subl	$_text, %ebx /* %ebx = offset for runtime symbols */
252
+
253
+/*****************************************************************************
254
+ * Copy prefix to storage area within Etherboot image.
255
+ *****************************************************************************
256
+ */
257
+	popl	%esi		/* Prefix source physical address */
258
+	pushl	%edi
259
+	leal	_prefix_copy(%ebx), %edi /* Prefix copy phys. addr. */
260
+	leal	_eprefix_copy(%ebx), %ecx
261
+	subl	%edi, %ecx	/* Prefix copy size */
262
+	rep movsb		/* Forward copy of prefix */
263
+	popl	%edi		/* Restore image target physical address */
264
+
265
+/*****************************************************************************
266
+ * Record base memory used by Etherboot image
267
+ *****************************************************************************
268
+ */
269
+	movl	%edi, _prefix_image_basemem (%ebx)
270
+
271
+/*****************************************************************************
272
+ * Jump to start of the image (i.e. the decompressor, or start32 if
273
+ * non-compressed).
274
+ *****************************************************************************
275
+ */
276
+	pushl	$0		/* Inform start32 that exit path is 16-bit */
277
+	jmpl	*%edi		/* Jump to image */
278
+	
279
+	.balign 16
280
+	/* Etherboot needs to be 16byte aligned or data that
281
+	 * is virtually aligned is no longer physically aligned
282
+	 * which is just nasty in general.  16byte alignment 
283
+	 * should be sufficient though.
284
+	 */
285
+payload:

+ 8
- 0
src/arch/i386/core/start16.lds View File

@@ -0,0 +1,8 @@
1
+/* When linking with an uncompressed image, these symbols are not
2
+ * defined so we provide them here.
3
+ */
4
+
5
+__decompressor_uncompressed = 0 ;
6
+__decompressor__start = 0 ;
7
+
8
+INCLUDE arch/i386/core/start16z.lds

+ 65
- 0
src/arch/i386/core/start16z.lds View File

@@ -0,0 +1,65 @@
1
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2
+OUTPUT_ARCH(i386)
3
+
4
+/* Linker-generated symbols are prefixed with a double underscore.
5
+ * Decompressor symbols are prefixed with __decompressor_.  All other
6
+ * symbols are the same as in the original object file, i.e. the
7
+ * runtime addresses.
8
+ */
9
+
10
+ENTRY(_start16)
11
+
12
+SECTIONS {
13
+	.text : {
14
+		*(.text)
15
+	}
16
+	.payload : {
17
+		__payload_start = .;
18
+		*(.data)
19
+		__payload_end = .;
20
+	}
21
+
22
+	/* _payload_size is the size of the binary image appended to
23
+	 * start16, in bytes.
24
+	 */
25
+	__payload_size = __payload_end - __payload_start ;
26
+
27
+	/* _size is the size of the runtime image
28
+	 * (start32 + the C code), in bytes.
29
+	 */
30
+	__size = _end - _start ;
31
+
32
+	/* _decompressor_size is the size of the decompressor, in
33
+	 * bytes.  For a non-compressed image, start16.lds sets
34
+	 * _decompressor_uncompressed = _decompressor__start = 0.
35
+	 */
36
+	__decompressor_size = __decompressor_uncompressed - __decompressor__start ;
37
+
38
+	/* image__size is the total size of the image, after
39
+	 * decompression and including the decompressor if applicable.
40
+	 * It is therefore the amount of memory that start16's payload
41
+	 * needs in order to execute, in bytes.
42
+	 */
43
+	__image_size = __size + __decompressor_size ;
44
+
45
+	/* Amount to add to runtime symbols to obtain the offset of
46
+	 * that symbol within the image.
47
+	 */
48
+	__offset_adjust = __decompressor_size - _start ;
49
+
50
+	/* Calculations for the stack
51
+	 */
52
+	__stack_size = _estack - _stack ;
53
+	__offset_stack = _stack + __offset_adjust ;
54
+
55
+	/* Some symbols will be larger than 16 bits but guaranteed to
56
+	 * be multiples of 16.  We calculate them in paragraphs and
57
+	 * export these symbols which can be used in 16-bit code
58
+	 * without risk of overflow.
59
+	 */
60
+	__image_size_pgh = ( __image_size / 16 );
61
+	__start_pgh = ( _start / 16 );
62
+	__decompressor_size_pgh = ( __decompressor_size / 16 );
63
+	__offset_stack_pgh = ( __offset_stack / 16 );
64
+}
65
+

+ 767
- 0
src/arch/i386/core/start32.S View File

@@ -0,0 +1,767 @@
1
+/* #defines because ljmp wants a number, probably gas bug */
2
+/*	.equ	KERN_CODE_SEG,_pmcs-_gdt	*/
3
+#define	KERN_CODE_SEG	0x08
4
+	.equ	KERN_DATA_SEG,_pmds-_gdt
5
+/*	.equ	REAL_CODE_SEG,_rmcs-_gdt	*/
6
+#define	REAL_CODE_SEG	0x18
7
+	.equ	REAL_DATA_SEG,_rmds-_gdt
8
+	.equ	FLAT_CODE_SEG,_pmcs2-_gdt
9
+	.equ	FLAT_DATA_SEG,_pmds2-_gdt
10
+	.equ	CR0_PE,1
11
+#ifdef CONFIG_X86_64
12
+	.equ	LM_CODE_SEG,  _lmcs-_gdt
13
+	.equ	LM_DATA_SEG,  _lmds-_gdt
14
+#endif
15
+
16
+	.equ	MSR_K6_EFER,   0xC0000080
17
+	.equ	EFER_LME,      0x00000100
18
+	.equ	X86_CR4_PAE,   0x00000020
19
+	.equ	CR0_PG,        0x80000000
20
+
21
+#ifdef	GAS291
22
+#define DATA32 data32;
23
+#define ADDR32 addr32;
24
+#define	LJMPI(x)	ljmp	x
25
+#else
26
+#define DATA32 data32
27
+#define ADDR32 addr32
28
+/* newer GAS295 require #define	LJMPI(x)	ljmp	*x */
29
+#define	LJMPI(x)	ljmp	x
30
+#endif
31
+
32
+#define BOCHSBP xchgw %bx, %bx
33
+
34
+#include "callbacks.h"
35
+#define NUM_PUSHA_REGS (8)
36
+#define NUM_SEG_REGS (6)
37
+	
38
+/*
39
+ * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
40
+ * then you only have to take care of %ebx, %esi, %edi and %ebp.  These
41
+ * registers must not be altered under any circumstance.  All other registers
42
+ * may be clobbered without any negative side effects.  If you don't follow
43
+ * this rule then you'll run into strange effects that only occur on some
44
+ * gcc versions (because the register allocator may use different registers).
45
+ *
46
+ * All the data32 prefixes for the ljmp instructions are necessary, because
47
+ * the assembler emits code with a relocation address of 0.  This means that
48
+ * all destinations are initially negative, which the assembler doesn't grok,
49
+ * because for some reason negative numbers don't fit into 16 bits. The addr32
50
+ * prefixes are there for the same reasons, because otherwise the memory
51
+ * references are only 16 bit wide.  Theoretically they are all superfluous.
52
+ * One last note about prefixes: the data32 prefixes on all call _real_to_prot
53
+ * instructions could be removed if the _real_to_prot function is changed to
54
+ * deal correctly with 16 bit return addresses.  I tried it, but failed.
55
+ */
56
+
57
+/**************************************************************************
58
+ * START
59
+ *
60
+ * This file is no longer enterered from the top.  init.S will jump to
61
+ * either _in_call or _rm_in_call, depending on the processor mode
62
+ * when init.S was entered.
63
+ **************************************************************************/
64
+	.text
65
+	.arch i386
66
+	.code32
67
+	
68
+/**************************************************************************
69
+_IN_CALL - make a call in to Etherboot.
70
+**************************************************************************/
71
+
72
+/* There are two 32-bit entry points: _in_call and _in_call_far, for
73
+ * near calls and far calls respectively.  Both should be called with
74
+ * flat physical addresses.  They will result in a call to the C
75
+ * routine in_call(); see there for API details.
76
+ *
77
+ * Note that this routine makes fairly heavy use of the stack and no
78
+ * use of fixed data areas.  This is because it must be re-entrant;
79
+ * there may be more than one concurrent call in to Etherboot.
80
+ */
81
+
82
+#define IC_OFFSET_VA_LIST_PTR ( 0 )
83
+#define IC_OFFSET_VA_LIST_PTR_E ( IC_OFFSET_VA_LIST_PTR + 4 )
84
+#define IC_OFFSET_REGISTERS ( IC_OFFSET_VA_LIST_PTR_E )
85
+#define IC_OFFSET_REGISTERS_E ( IC_OFFSET_REGISTERS + ( NUM_PUSHA_REGS * 4 ) )
86
+#define IC_OFFSET_SEG_REGS ( IC_OFFSET_REGISTERS_E )
87
+#define IC_OFFSET_SEG_REGS_E ( IC_OFFSET_SEG_REGS + ( NUM_SEG_REGS * 2 ) )
88
+#define IC_OFFSET_GDT ( IC_OFFSET_SEG_REGS_E )
89
+#define IC_OFFSET_GDT_E ( IC_OFFSET_GDT + 8 )
90
+#define IC_OFFSET_FLAGS ( IC_OFFSET_GDT_E )
91
+#define IC_OFFSET_FLAGS_E ( IC_OFFSET_FLAGS + 4 )
92
+#define IC_OFFSET_RETADDR ( IC_OFFSET_FLAGS_E )
93
+#define IC_OFFSET_RETADDR_E ( IC_OFFSET_RETADDR + 8 )
94
+#define IC_OFFSET_ORIG_STACK ( IC_OFFSET_RETADDR )
95
+#define IC_OFFSET_OPCODE ( IC_OFFSET_ORIG_STACK + 8 )
96
+#define IC_OFFSET_OPCODE_E ( IC_OFFSET_OPCODE + 4 )
97
+#define IC_OFFSET_VA_LIST ( IC_OFFSET_OPCODE_E )
98
+	
99
+	.code32
100
+	.globl _in_call
101
+	.globl _in_call_far
102
+_in_call:
103
+	/* Expand to far return address */
104
+	pushl	%eax			/* Store %eax */
105
+	xorl	%eax, %eax
106
+	movw	%cs, %ax
107
+	xchgl	%eax, 4(%esp)		/* 4(%esp) = %cs, %eax = ret addr */
108
+	xchgl	%eax, 0(%esp)		/* 0(%esp) = ret addr, restore %eax */
109
+_in_call_far:
110
+	/* Store flags */
111
+	pushfl
112
+	/* Store the GDT */
113
+	subl	$8, %esp
114
+	sgdt	0(%esp)
115
+	/* Store segment register values */
116
+	pushw	%gs
117
+	pushw	%fs
118
+	pushw	%es
119
+	pushw	%ds
120
+	pushw	%ss
121
+	pushw	%cs
122
+	/* Store general-purpose register values */
123
+	pushal
124
+	/* Replace %esp in store with physical %esp value on entry */
125
+	leal	(IC_OFFSET_ORIG_STACK - IC_OFFSET_REGISTERS)(%esp), %eax
126
+	movl	%eax, (IC_OFFSET_REGISTERS - IC_OFFSET_REGISTERS + 12)(%esp)
127
+	/* Store va_list pointer (physical address) */
128
+	leal	(IC_OFFSET_VA_LIST - IC_OFFSET_VA_LIST_PTR_E)(%esp), %eax
129
+	pushl	%eax
130
+	/* IC_OFFSET_*(%esp) are now valid */
131
+
132
+	/* Switch to virtual addresses */
133
+	call	_phys_to_virt
134
+
135
+	/* Fixup the va_list pointer */
136
+	movl	virt_offset, %ebp
137
+	subl	%ebp, IC_OFFSET_VA_LIST_PTR(%esp)
138
+
139
+	/* Check opcode for EB_USE_INTERNAL_STACK flag */
140
+	movl	IC_OFFSET_OPCODE(%esp), %eax
141
+	testl	$EB_USE_INTERNAL_STACK, %eax
142
+	je	2f
143
+	/* Use internal stack flag set */
144
+	/* Check %esp is not already in internal stack range */
145
+	leal	_stack, %esi		/* %esi = bottom of internal stack */
146
+	leal	_estack, %edi		/* %edi = top of internal stack */
147
+	cmpl	%esi, %esp
148
+	jb	1f
149
+	cmpl	%edi, %esp
150
+	jbe	2f
151
+1:	/* %esp not currently in internal stack range */
152
+	movl	%esp, %esi		/* %esi = original stack */
153
+	movl	$IC_OFFSET_OPCODE_E, %ecx /* %ecx = length to transfer */
154
+	subl	%ecx, %edi		/* %edi = internal stack pos */
155
+	movl	%edi, %esp		/*  = new %esp */
156
+	rep movsb			/* Copy data to internal stack */
157
+2:
158
+
159
+	/* Call to C code */
160
+	call	i386_in_call
161
+
162
+	/* Set %eax (return code from C) in registers structure on
163
+	 * stack, so that we return it to the caller.
164
+	 */
165
+	movl	%eax, (IC_OFFSET_REGISTERS + 28)(%esp)
166
+
167
+	/* Calculate physical continuation address */
168
+	movl	virt_offset, %ebp
169
+	movzwl	(IC_OFFSET_SEG_REGS + 0)(%esp), %eax	/* %cs */
170
+	movzwl	(IC_OFFSET_SEG_REGS + 2)(%esp), %ebx	/* %ss */
171
+	pushl	%eax			/* Continuation segment */
172
+	leal	1f(%ebp), %eax
173
+	pushl	%eax			/* Continuation offset */
174
+	
175
+	/* Restore caller's GDT */
176
+	cli				/* Temporarily disable interrupts */
177
+	lgdt	(8+IC_OFFSET_GDT)(%esp)
178
+	/* Reset %ss and adjust %esp */
179
+	movw	%bx, %ss
180
+	addl	%ebp, %esp
181
+	lret				/* Reload %cs:eip, flush prefetch */
182
+1:
183
+
184
+	/* Skip va_list ptr */
185
+	popl	%eax
186
+	/* Reload general-purpose registers to be returned */
187
+	popal
188
+	/* Reload segment registers as passed in from caller */
189
+	popw	%gs
190
+	popw	%fs
191
+	popw	%es
192
+	popw	%ds
193
+	addl	$(4+8), %esp	/* Skip %cs, %ss and GDT (already reloaded) */
194
+	/* Restore flags (including revert of interrupt status) */
195
+	popfl
196
+
197
+	/* Restore physical %esp from entry.  It will only be
198
+	 * different if EB_USE_INTERNAL_STACK was specified.
199
+	 */
200
+	movl	( 12 + IC_OFFSET_REGISTERS - IC_OFFSET_RETADDR )(%esp), %esp
201
+		
202
+	/* Check for EB_SKIP_OPCODE */
203
+	pushfl
204
+	testl	$EB_SKIP_OPCODE, 12(%esp)
205
+	jnz	1f
206
+	/* Normal return */
207
+	popfl
208
+	lret
209
+1:	/* Return and skip opcode */
210
+	popfl
211
+	lret	$4
212
+	
213
+/**************************************************************************
214
+RELOCATE_TO - relocate etherboot to the specified address
215
+**************************************************************************/
216
+	.globl relocate_to
217
+relocate_to:
218
+	/* Save the callee save registers */
219
+	pushl	%ebp
220
+	pushl	%esi
221
+	pushl	%edi
222
+
223
+	/* Compute the virtual destination address */
224
+	movl	16(%esp), %edi	# dest
225
+	subl	virt_offset, %edi
226
+	
227
+
228
+	/* Compute the new value of virt_offset */
229
+	movl	16(%esp), %ebp	# virt_offset
230
+	subl	$_text, %ebp
231
+
232
+	/* Fixup the gdt */
233
+	pushl	$_pmcs
234
+	pushl	%ebp		# virt_offset
235
+	call	set_seg_base
236
+	addl	$8, %esp
237
+
238
+	/* Fixup gdtarg */
239
+	leal	_gdt(%ebp), %eax
240
+	movl	%eax, gdtarg +2
241
+
242
+	/* Fixup virt_offset */
243
+	movl	%ebp, virt_offset
244
+
245
+	/* Load the move parameters */
246
+	movl	$_text, %esi
247
+	movl	$_end, %ecx
248
+	subl	%esi, %ecx
249
+
250
+	/* Move etherboot uses %esi, %edi, %ecx */
251
+	rep 
252
+	movsb
253
+
254
+	/* Reload the gdt */
255
+	cs
256
+	lgdt	gdtarg
257
+
258
+	/* Reload %cs */
259
+	ljmp	$KERN_CODE_SEG, $1f
260
+1:
261
+	/* reload other segment registers */
262
+	movl	$KERN_DATA_SEG, %eax
263
+	movl	%eax,%ds
264
+	movl	%eax,%es
265
+	movl	%eax,%ss
266
+	movl	%eax,%fs
267
+	movl	%eax,%gs
268
+
269
+	/* Restore the callee save registers */
270
+	popl	%edi
271
+	popl	%esi
272
+	popl	%ebp
273
+
274
+	/* return */
275
+	ret
276
+
277
+/**************************************************************************
278
+XSTART32 - Transfer control to the kernel just loaded
279
+**************************************************************************/
280
+	.globl xstart32
281
+xstart32:
282
+	/* Save the callee save registers */
283
+	movl	%ebp, os_regs + 32
284
+	movl	%esi, os_regs + 36
285
+	movl	%edi, os_regs + 40
286
+	movl	%ebx, os_regs + 44
287
+
288
+	/* save the return address */
289
+	popl	%eax
290
+	movl	%eax, os_regs + 48
291
+
292
+	/* save the stack pointer */
293
+	movl	%esp, os_regs + 52
294
+
295
+	/* Get the new destination address */
296
+	popl	%ecx
297
+
298
+	/* Store the physical address of xend on the stack */
299
+	movl	$xend32, %ebx
300
+	addl	virt_offset, %ebx
301
+	pushl	%ebx
302
+
303
+	/* Store the destination address on the stack */
304
+	pushl	$FLAT_CODE_SEG
305
+	pushl	%ecx
306
+
307
+	/* Cache virt_offset */
308
+	movl	virt_offset, %ebp
309
+	
310
+	/* Switch to using physical addresses */
311
+	call	_virt_to_phys
312
+
313
+	/* Save the target stack pointer */
314
+	movl	%esp, os_regs + 12(%ebp)
315
+	leal	os_regs(%ebp), %esp
316
+
317
+	/* Store the pointer to os_regs */
318
+	movl	%esp, os_regs_ptr(%ebp)
319
+
320
+	/* Load my new registers */
321
+	popal
322
+	movl	(-32 + 12)(%esp), %esp
323
+
324
+	/* Jump to the new kernel
325
+	 * The lret switches to a flat code segment
326
+	 */
327
+	lret
328
+
329
+	.balign 4
330
+	.globl xend32
331
+xend32:
332
+	/* Fixup %eflags */
333
+	nop
334
+	cli
335
+	cld
336
+	
337
+	/* Load %esp with &os_regs + virt_offset */
338
+	.byte	0xbc /* movl $0, %esp */
339
+os_regs_ptr:
340
+	.long	0
341
+
342
+	/* Save the result registers */
343
+	addl	$32, %esp
344
+	pushal
345
+
346
+	/* Compute virt_offset */
347
+	movl	%esp, %ebp
348
+	subl	$os_regs, %ebp
349
+	
350
+	/* Load the stack pointer */
351
+	movl	52(%esp), %esp
352
+
353
+	/* Enable the virtual addresses */
354
+	leal	_phys_to_virt(%ebp), %eax
355
+	call	*%eax
356
+
357
+	/* Restore the callee save registers */
358
+	movl	os_regs + 32, %ebp
359
+	movl	os_regs + 36, %esi
360
+	movl	os_regs + 40, %edi
361
+	movl	os_regs + 44, %ebx
362
+	movl	os_regs + 48, %edx
363
+	movl	os_regs + 52, %esp
364
+
365
+	/* Get the C return value */
366
+	movl	os_regs + 28, %eax
367
+
368
+	jmpl	*%edx
369
+
370
+#ifdef CONFIG_X86_64
371
+	.arch	sledgehammer
372
+/**************************************************************************
373
+XSTART_lm - Transfer control to the kernel just loaded in long mode
374
+**************************************************************************/
375
+	.globl xstart_lm
376
+xstart_lm:
377
+	/* Save the callee save registers */
378
+	pushl	%ebp
379
+	pushl	%esi
380
+	pushl	%edi
381
+	pushl	%ebx
382
+
383
+	/* Cache virt_offset && (virt_offset & 0xfffff000) */
384
+	movl	virt_offset, %ebp
385
+	movl	%ebp, %ebx
386
+	andl	$0xfffff000, %ebx
387
+
388
+	/* Switch to using physical addresses */
389
+	call	_virt_to_phys
390
+
391
+	/* Initialize the page tables */
392
+	/* Level 4 */
393
+	leal	0x23 + pgt_level3(%ebx), %eax
394
+	leal	pgt_level4(%ebx), %edi
395
+	movl	%eax, (%edi)
396
+
397
+	/* Level 3 */
398
+	leal	0x23 + pgt_level2(%ebx), %eax
399
+	leal	pgt_level3(%ebx), %edi
400
+	movl	%eax, 0x00(%edi)
401
+	addl	$4096, %eax
402
+	movl	%eax, 0x08(%edi)
403
+	addl	$4096, %eax
404
+	movl	%eax, 0x10(%edi)
405
+	addl	$4096, %eax
406
+	movl	%eax, 0x18(%edi)
407
+
408
+	/* Level 2 */
409
+	movl	$0xe3, %eax
410
+	leal	pgt_level2(%ebx), %edi
411
+	leal	16384(%edi), %esi
412
+pgt_level2_loop:
413
+	movl	%eax, (%edi)
414
+	addl	$8, %edi
415
+	addl	$0x200000, %eax
416
+	cmp	%esi, %edi
417
+	jne	pgt_level2_loop
418
+
419
+	/* Point at the x86_64 page tables */
420
+	leal	pgt_level4(%ebx), %edi
421
+	movl	%edi, %cr3
422
+
423
+
424
+	/* Setup for the return from 64bit mode */
425
+	/* 64bit align the stack */
426
+	movl	%esp, %ebx		/* original stack pointer + 16 */
427
+	andl	$0xfffffff8, %esp
428
+
429
+	/* Save original stack pointer + 16 */
430
+	pushl	%ebx
431
+
432
+	/* Save virt_offset */
433
+	pushl	%ebp
434
+
435
+	/* Setup for the jmp to 64bit long mode */
436
+	leal	start_lm(%ebp), %eax
437
+	movl	%eax, 0x00 + start_lm_addr(%ebp)
438
+	movl	$LM_CODE_SEG, %eax
439
+	movl	%eax, 0x04 + start_lm_addr(%ebp)
440
+
441
+	/* Setup for the jump out of 64bit long mode */
442
+	leal	end_lm(%ebp), %eax
443
+	movl	%eax, 0x00 + end_lm_addr(%ebp)
444
+	movl	$FLAT_CODE_SEG, %eax
445
+	movl	%eax, 0x04 + end_lm_addr(%ebp)
446
+
447
+	/* Enable PAE mode */
448
+	movl	%cr4, %eax
449
+	orl	$X86_CR4_PAE, %eax
450
+	movl	%eax, %cr4
451
+
452
+	/* Enable long mode */
453
+	movl	$MSR_K6_EFER, %ecx
454
+	rdmsr
455
+	orl	$EFER_LME, %eax
456
+	wrmsr
457
+
458
+	/* Start paging, entering 32bit compatiblity mode */
459
+	movl	%cr0, %eax
460
+	orl	$CR0_PG, %eax
461
+	movl	%eax, %cr0
462
+
463
+	/* Enter 64bit long mode */
464
+	ljmp	*start_lm_addr(%ebp)
465
+	.code64
466
+start_lm:
467
+	/* Load 64bit data segments */
468
+	movl	$LM_DATA_SEG, %eax
469
+	movl	%eax, %ds
470
+	movl	%eax, %es
471
+	movl	%eax, %ss
472
+
473
+	andq	$0xffffffff, %rbx
474
+	/* Get the address to jump to */
475
+	movl	20(%rbx), %edx
476
+	andq	$0xffffffff, %rdx
477
+	
478
+	/* Get the argument pointer */
479
+	movl	24(%rbx), %ebx
480
+	andq	$0xffffffff, %rbx
481
+
482
+	/* Jump to the 64bit code */
483
+	call	*%rdx
484
+
485
+	/* Preserve the result */
486
+	movl	%eax, %edx
487
+
488
+	/* Fixup %eflags */
489
+	cli
490
+	cld
491
+
492
+	/* Switch to 32bit compatibility mode */
493
+	ljmp	*end_lm_addr(%rip)
494
+
495
+	.code32
496
+end_lm:
497
+	/* Disable paging */
498
+	movl	%cr0, %eax
499
+	andl	$~CR0_PG, %eax
500
+	movl	%eax, %cr0
501
+
502
+	/* Disable long mode */
503
+	movl	$MSR_K6_EFER, %ecx
504
+	rdmsr
505
+	andl	$~EFER_LME, %eax
506
+	wrmsr
507
+
508
+	/* Disable PAE */
509
+	movl	%cr4, %eax
510
+	andl	$~X86_CR4_PAE, %eax
511
+	movl	%eax, %cr4
512
+	
513
+	/* Compute virt_offset */
514
+	popl	%ebp
515
+
516
+	/* Compute the original stack pointer + 16 */
517
+	popl	%ebx
518
+	movl	%ebx, %esp
519
+
520
+	/* Enable the virtual addresses */
521
+	leal	_phys_to_virt(%ebp), %eax
522
+	call	*%eax
523
+
524
+	/* Restore the callee save registers */
525
+	popl	%ebx
526
+	popl	%esi
527
+	popl	%edi
528
+	popl	%ebp
529
+
530
+	/* Get the C return value */
531
+	movl	%edx, %eax
532
+
533
+	/* Return */
534
+	ret
535
+
536
+	.arch i386
537
+#endif /* CONFIG_X86_64 */
538
+
539
+/**************************************************************************
540
+SETJMP - Save stack context for non-local goto
541
+**************************************************************************/
542
+	.globl	setjmp
543
+setjmp:
544
+	movl	4(%esp),%ecx		/* jmpbuf */
545
+	movl	0(%esp),%edx		/* return address */
546
+	movl	%edx,0(%ecx)
547
+	movl	%ebx,4(%ecx)
548
+	movl	%esp,8(%ecx)
549
+	movl	%ebp,12(%ecx)
550
+	movl	%esi,16(%ecx)
551
+	movl	%edi,20(%ecx)
552
+	movl	$0,%eax
553
+	ret
554
+
555
+/**************************************************************************
556
+LONGJMP - Non-local jump to a saved stack context
557
+**************************************************************************/
558
+	.globl	longjmp
559
+longjmp:
560
+	movl	4(%esp),%edx		/* jumpbuf */
561
+	movl	8(%esp),%eax		/* result */
562
+	movl	0(%edx),%ecx
563
+	movl	4(%edx),%ebx
564
+	movl	8(%edx),%esp
565
+	movl	12(%edx),%ebp
566
+	movl	16(%edx),%esi
567
+	movl	20(%edx),%edi
568
+	cmpl	$0,%eax
569
+	jne	1f
570
+	movl	$1,%eax
571
+1:	movl	%ecx,0(%esp)
572
+	ret
573
+
574
+/**************************************************************************
575
+_VIRT_TO_PHYS - Transition from virtual to physical addresses
576
+		Preserves all preservable registers and flags
577
+**************************************************************************/
578
+	.globl _virt_to_phys
579
+_virt_to_phys:
580
+	pushfl
581
+	pushl	%ebp
582
+	pushl	%eax
583
+	movl	virt_offset, %ebp	/* Load virt_offset */
584
+	addl	%ebp, 12(%esp)		/* Adjust the return address */
585
+
586
+	/* reload the code segment */
587
+	pushl	$FLAT_CODE_SEG
588
+	leal	1f(%ebp), %eax
589
+	pushl	%eax
590
+	lret
591
+
592
+1:
593
+	/* reload other segment registers */
594
+	movl	$FLAT_DATA_SEG, %eax
595
+	movl	%eax, %ds
596
+	movl	%eax, %es	
597
+	movl	%eax, %ss	
598
+	addl	%ebp, %esp		/* Adjust the stack pointer */
599
+	movl	%eax, %fs	
600
+	movl	%eax, %gs
601
+
602
+	popl	%eax
603
+	popl	%ebp
604
+	popfl
605
+	ret
606
+
607
+
608
+/**************************************************************************
609
+_PHYS_TO_VIRT - Transition from using physical to virtual addresses
610
+		Preserves all preservable registers and flags
611
+**************************************************************************/
612
+	.globl _phys_to_virt
613
+_phys_to_virt:
614
+	pushfl
615
+	pushl	%ebp
616
+	pushl	%eax
617
+
618
+	call	1f
619
+1:	popl	%ebp
620
+	subl	$1b, %ebp
621
+	movl	%ebp, virt_offset(%ebp)
622
+
623
+	/* Fixup the gdt */
624
+	leal	_pmcs(%ebp), %eax
625
+	pushl	%eax
626
+	pushl	%ebp
627
+	call	set_seg_base
628
+	addl	$8, %esp
629
+
630
+	/* Fixup gdtarg */
631
+	leal	_gdt(%ebp), %eax
632
+	movl	%eax, (gdtarg+2)(%ebp)
633
+
634
+	/* Load the global descriptor table */
635
+	cli
636
+	lgdt	%cs:gdtarg(%ebp)
637
+	ljmp	$KERN_CODE_SEG, $1f
638
+1:
639
+	/* reload other segment regsters */
640
+	movl	$KERN_DATA_SEG, %eax
641
+	movl	%eax, %ds
642
+	movl	%eax, %es	
643
+	movl	%eax, %ss	
644
+	subl	%ebp, %esp	/* Adjust the stack pointer */
645
+	movl	%eax, %fs	
646
+	movl	%eax, %gs
647
+
648
+	subl	%ebp, 12(%esp)	/* Adjust the return address */
649
+	popl	%eax
650
+	popl	%ebp
651
+	popfl
652
+	ret
653
+	
654
+
655
+/**************************************************************************
656
+SET_SEG_BASE - Set the base address of a segment register
657
+**************************************************************************/
658
+	.globl set_seg_base
659
+set_seg_base:
660
+	pushl	%eax
661
+	pushl	%ebx
662
+	movl	12(%esp), %eax		/* %eax = base address */
663
+	movl	16(%esp), %ebx		/* %ebx = &code_descriptor */
664
+	movw	%ax, (0+2)(%ebx)	/* CS base bits 0-15 */
665
+	movw	%ax, (8+2)(%ebx)	/* DS base bits 0-15 */
666
+	shrl	$16, %eax
667
+	movb	%al, (0+4)(%ebx)	/* CS base bits 16-23 */
668
+	movb	%al, (8+4)(%ebx)	/* DS base bits 16-23 */
669
+	movb	%ah, (0+7)(%ebx)	/* CS base bits 24-31 */
670
+	movb	%ah, (8+7)(%ebx)	/* DS base bits 24-31 */
671
+	popl	%ebx
672
+	popl	%eax
673
+	ret
674
+	
675
+/**************************************************************************
676
+GLOBAL DESCRIPTOR TABLE
677
+**************************************************************************/
678
+	.data
679
+	.align	4
680
+
681
+	.globl	_gdt
682
+	.globl	gdtarg
683
+_gdt:
684
+gdtarg:
685
+	.word	_gdt_end - _gdt - 1	/* limit */
686
+	.long	_gdt			/* addr */
687
+	.word	0
688
+
689
+	.globl	_pmcs
690
+_pmcs:
691
+	/* 32 bit protected mode code segment */
692
+	.word	0xffff,0
693
+	.byte	0,0x9f,0xcf,0
694
+
695
+_pmds:
696
+	/* 32 bit protected mode data segment */
697
+	.word	0xffff,0
698
+	.byte	0,0x93,0xcf,0
699
+
700
+_rmcs:
701
+	/* 16 bit real mode code segment */
702
+	.word	0xffff,(0&0xffff)
703
+	.byte	(0>>16),0x9b,0x00,(0>>24)
704
+
705
+_rmds:
706
+	/* 16 bit real mode data segment */
707
+	.word	0xffff,(0&0xffff)
708
+	.byte	(0>>16),0x93,0x00,(0>>24)
709
+
710
+_pmcs2:
711
+	/* 32 bit protected mode code segment, base 0 */
712
+	.word	0xffff,0
713
+	.byte	0,0x9f,0xcf,0
714
+
715
+_pmds2:
716
+	/* 32 bit protected mode data segment, base 0 */
717
+	.word	0xffff,0
718
+	.byte	0,0x93,0xcf,0
719
+
720
+#ifdef CONFIG_X86_64
721
+_lmcs:
722
+	/* 64bit long mode code segment, base 0 */
723
+	.word	0xffff, 0
724
+	.byte	0x00, 0x9f, 0xaf , 0x00
725
+_lmds:
726
+	/* 64bit long mode data segment, base 0 */
727
+	.word	0xffff, 0
728
+	.byte	0x00, 0x93, 0xcf, 0x00
729
+#endif
730
+_gdt_end:
731
+
732
+	/* The initial register contents */
733
+	.balign 4
734
+	.globl initial_regs
735
+initial_regs:
736
+	.fill 8, 4, 0
737
+
738
+	/* The virtual address offset  */	
739
+	.globl virt_offset
740
+virt_offset:
741
+	.long  	0
742
+
743
+	.section ".stack"
744
+	.p2align 3
745
+	/* allocate a 4K stack in the stack segment */
746
+	.globl	_stack
747
+_stack:
748
+	.space 4096
749
+	.globl	_estack
750
+_estack:
751
+#ifdef CONFIG_X86_64
752
+	.section ".bss"
753
+	.p2align 12
754
+	/* Include a dummy space in case we are loaded badly aligned */
755
+	.space 4096
756
+	/* Reserve enough space for a page table convering 4GB with 2MB pages */
757
+pgt_level4:	
758
+	.space 4096
759
+pgt_level3:	
760
+	.space 4096
761
+pgt_level2:	
762
+	.space 16384
763
+start_lm_addr:
764
+	.space	8
765
+end_lm_addr:
766
+	.space	8
767
+#endif

+ 201
- 0
src/arch/i386/core/tagged_loader.c View File

@@ -0,0 +1,201 @@
1
+#include "realmode.h"
2
+#include "segoff.h"
3
+
4
+struct segheader
5
+{
6
+	unsigned char length;
7
+	unsigned char vendortag;
8
+	unsigned char reserved;
9
+	unsigned char flags;
10
+	unsigned long loadaddr;
11
+	unsigned long imglength;
12
+	unsigned long memlength;
13
+};
14
+
15
+struct imgheader
16
+{
17
+	unsigned long magic;
18
+	unsigned long length;			/* and flags */
19
+	union
20
+	{
21
+		segoff_t segoff;
22
+		unsigned long location;
23
+	} u;
24
+	unsigned long execaddr;
25
+};
26
+
27
+/* Keep all context about loaded image in one place */
28
+static struct tagged_context
29
+{
30
+	struct imgheader	img;			/* copy of header */
31
+	unsigned long		linlocation;		/* addr of header */
32
+	unsigned long		last0, last1;		/* of prev segment */
33
+	unsigned long		segaddr, seglen;	/* of current segment */
34
+	unsigned char		segflags;
35
+	unsigned char		first;
36
+	unsigned long		curaddr;
37
+} tctx;
38
+
39
+#define	TAGGED_PROGRAM_RETURNS	(tctx.img.length & 0x00000100)	/* bit 8 */
40
+#define	LINEAR_EXEC_ADDR	(tctx.img.length & 0x80000000)	/* bit 31 */
41
+
42
+static sector_t tagged_download(unsigned char *data, unsigned int len, int eof);
43
+void xstart16 (unsigned long execaddr, segoff_t location,
44
+	       void *bootp);
45
+
46
+static inline os_download_t tagged_probe(unsigned char *data, unsigned int len)
47
+{
48
+	struct segheader	*sh;
49
+	unsigned long loc;
50
+	if (*((uint32_t *)data) != 0x1B031336L) {
51
+		return 0;
52
+	}
53
+	printf("(NBI)");
54
+	/* If we don't have enough data give up */
55
+	if (len < 512)
56
+		return dead_download;
57
+	/* Zero all context info */
58
+	memset(&tctx, 0, sizeof(tctx));
59
+	/* Copy first 4 longwords */
60
+	memcpy(&tctx.img, data, sizeof(tctx.img));
61
+	/* Memory location where we are supposed to save it */
62
+	tctx.segaddr = tctx.linlocation = 
63
+		((tctx.img.u.segoff.segment) << 4) + tctx.img.u.segoff.offset;
64
+	if (!prep_segment(tctx.segaddr, tctx.segaddr + 512, tctx.segaddr + 512,
65
+			  0, 512)) {
66
+		return dead_download;
67
+	}
68
+	/* Now verify the segments we are about to load */
69
+	loc = 512;
70
+	for(sh = (struct segheader *)(data
71
+				      + ((tctx.img.length & 0x0F) << 2)
72
+				      + ((tctx.img.length & 0xF0) >> 2) ); 
73
+		(sh->length > 0) && ((unsigned char *)sh < data + 512); 
74
+		sh = (struct segheader *)((unsigned char *)sh
75
+					  + ((sh->length & 0x0f) << 2) + ((sh->length & 0xf0) >> 2)) ) {
76
+		if (!prep_segment(
77
+			sh->loadaddr,
78
+			sh->loadaddr + sh->imglength,
79
+			sh->loadaddr + sh->imglength,
80
+			loc, loc + sh->imglength)) {
81
+			return dead_download;
82
+		}
83
+		loc = loc + sh->imglength;
84
+		if (sh->flags & 0x04) 
85
+			break;
86
+	}
87
+	if (!(sh->flags & 0x04))
88
+		return dead_download;
89
+	/* Grab a copy */
90
+	memcpy(phys_to_virt(tctx.segaddr), data, 512);
91
+	/* Advance to first segment descriptor */
92
+	tctx.segaddr += ((tctx.img.length & 0x0F) << 2)
93
+		+ ((tctx.img.length & 0xF0) >> 2);
94
+	/* Remember to skip the first 512 data bytes */
95
+	tctx.first = 1;
96
+	
97
+	return tagged_download;
98
+
99
+}
100
+static sector_t tagged_download(unsigned char *data, unsigned int len, int eof)
101
+{
102
+	int	i;
103
+
104
+	if (tctx.first) {
105
+		tctx.first = 0;
106
+		if (len > 512) {
107
+			len -= 512;
108
+			data += 512;
109
+			/* and fall through to deal with rest of block */
110
+		} else 
111
+			return 0;
112
+	}
113
+	for (;;) {
114
+		if (len == 0) /* Detect truncated files */
115
+			eof = 0;
116
+		while (tctx.seglen == 0) {
117
+			struct segheader	sh;
118
+			if (tctx.segflags & 0x04) {
119
+				done(1);
120
+				if (LINEAR_EXEC_ADDR) {
121
+					int result;
122
+					/* no gateA20_unset for PM call */
123
+					result = xstart32(tctx.img.execaddr,
124
+						virt_to_phys(&loaderinfo),
125
+						tctx.linlocation,
126
+						virt_to_phys(BOOTP_DATA_ADDR));
127
+					printf("Secondary program returned %d\n",
128
+						result);
129
+					if (!TAGGED_PROGRAM_RETURNS) {
130
+						/* We shouldn't have returned */
131
+						result = -2;
132
+					}
133
+					if (result == 0)
134
+						result = -2;
135
+					longjmp(restart_etherboot, result);
136
+						
137
+				} else {
138
+					gateA20_unset();
139
+					xstart16(tctx.img.execaddr, 
140
+						 tctx.img.u.segoff,
141
+						 BOOTP_DATA_ADDR);
142
+					longjmp(restart_etherboot, -2);
143
+				}
144
+			}
145
+			sh = *((struct segheader *)phys_to_virt(tctx.segaddr));
146
+			tctx.seglen = sh.imglength;
147
+			if ((tctx.segflags = sh.flags & 0x03) == 0)
148
+				tctx.curaddr = sh.loadaddr;
149
+			else if (tctx.segflags == 0x01)
150
+				tctx.curaddr = tctx.last1 + sh.loadaddr;
151
+			else if (tctx.segflags == 0x02)
152
+				tctx.curaddr = (Address)(meminfo.memsize * 1024L
153
+						    + 0x100000L)
154
+					- sh.loadaddr;
155
+			else
156
+				tctx.curaddr = tctx.last0 - sh.loadaddr;
157
+			tctx.last1 = (tctx.last0 = tctx.curaddr) + sh.memlength;
158
+			tctx.segflags = sh.flags;
159
+			tctx.segaddr += ((sh.length & 0x0F) << 2)
160
+				+ ((sh.length & 0xF0) >> 2);
161
+			/* Avoid lock-up */
162
+			if ( sh.length == 0 ) longjmp(restart_etherboot, -2); 
163
+		}
164
+		if ((len <= 0) && !eof)
165
+			break;
166
+		i = (tctx.seglen > len) ? len : tctx.seglen;
167
+		memcpy(phys_to_virt(tctx.curaddr), data, i);
168
+		tctx.seglen -= i;
169
+		tctx.curaddr += i;
170
+		len -= i;
171
+		data += i;
172
+	} 
173
+	return 0;
174
+}
175
+
176
+void xstart16 (unsigned long execaddr, segoff_t location,
177
+	       void *bootp) {
178
+	struct {
179
+		segoff_t execaddr;
180
+		segoff_t location;
181
+		segoff_t bootp;
182
+	} PACKED in_stack;
183
+
184
+	/* AFAICT, execaddr is actually already a segment:offset */
185
+	*((unsigned long *)&in_stack.execaddr) = execaddr;
186
+	in_stack.location = location;
187
+	in_stack.bootp.segment = SEGMENT(bootp);
188
+	in_stack.bootp.offset = OFFSET(bootp);
189
+
190
+	RM_FRAGMENT(rm_xstart16,
191
+		"popl %eax\n\t"	/* Calculated lcall */
192
+		"pushw %cs\n\t" 
193
+		"call 1f\n1:\tpopw %bp\n\t" 
194
+		"leaw (2f-1b)(%bp), %bx\n\t" 
195
+		"pushw %bx\n\t" 
196
+		"pushl %eax\n\t"
197
+		"lret\n2:\n\t"
198
+	);
199
+       
200
+	real_call ( rm_xstart16, &in_stack, NULL );
201
+}

+ 94
- 0
src/arch/i386/core/video_subr.c View File

@@ -0,0 +1,94 @@
1
+/*
2
+ *
3
+ * modified from linuxbios code
4
+ * by Cai Qiang <rimy2000@hotmail.com>
5
+ *
6
+ */
7
+
8
+#ifdef CONSOLE_DIRECT_VGA
9
+
10
+#include <etherboot.h>
11
+#include <vga.h>
12
+
13
+static char *vidmem;		/* The video buffer */
14
+static int video_line, video_col;
15
+
16
+#define VIDBUFFER 0xB8000	
17
+
18
+static void memsetw(void *s, int c, unsigned int n)
19
+{
20
+	int i;
21
+	u16 *ss = (u16 *) s;
22
+
23
+	for (i = 0; i < n; i++) {
24
+		ss[i] = ( u16 ) c;
25
+	}
26
+}
27
+
28
+void video_init(void)
29
+{
30
+	static int inited=0;
31
+
32
+	vidmem = (unsigned char *)phys_to_virt(VIDBUFFER);
33
+
34
+	if (!inited) {
35
+		video_line = 0;
36
+		video_col = 0;
37
+	
38
+	 	memsetw(vidmem, VGA_ATTR_CLR_WHT, 2*1024); //
39
+
40
+		inited=1;
41
+	}
42
+}
43
+
44
+static void video_scroll(void)
45
+{
46
+	int i;
47
+
48
+	memcpy(vidmem, vidmem + COLS * 2, (LINES - 1) * COLS * 2);
49
+	for (i = (LINES - 1) * COLS * 2; i < LINES * COLS * 2; i += 2)
50
+		vidmem[i] = ' ';
51
+}
52
+
53
+void vga_putc(unsigned char byte)
54
+{
55
+	if (byte == '\n') {
56
+		video_line++;
57
+		video_col = 0;
58
+
59
+	} else if (byte == '\r') {
60
+		video_col = 0;
61
+
62
+	} else if (byte == '\b') {
63
+		video_col--;
64
+
65
+	} else if (byte == '\t') {
66
+		video_col += 4;
67
+
68
+	} else if (byte == '\a') {
69
+		//beep
70
+		//beep(500);
71
+
72
+	} else {
73
+		vidmem[((video_col + (video_line *COLS)) * 2)] = byte;
74
+		vidmem[((video_col + (video_line *COLS)) * 2) +1] = VGA_ATTR_CLR_WHT;
75
+		video_col++;
76
+	}
77
+	if (video_col < 0) {
78
+		video_col = 0;
79
+	}
80
+	if (video_col >= COLS) {
81
+		video_line++;
82
+		video_col = 0;
83
+	}
84
+	if (video_line >= LINES) {
85
+		video_scroll();
86
+		video_line--;
87
+	}
88
+	// move the cursor
89
+	write_crtc((video_col + (video_line *COLS)) >> 8, CRTC_CURSOR_HI);
90
+	write_crtc((video_col + (video_line *COLS)) & 0x0ff, CRTC_CURSOR_LO);
91
+}
92
+
93
+#endif
94
+

+ 273
- 0
src/arch/i386/core/wince_loader.c View File

@@ -0,0 +1,273 @@
1
+#define LOAD_DEBUG	0
2
+
3
+static int get_x_header(unsigned char *data, unsigned long now);
4
+static void jump_2ep();
5
+static unsigned char ce_signature[] = {'B', '0', '0', '0', 'F', 'F', '\n',};
6
+static char ** ep;
7
+
8
+#define BOOT_ARG_PTR_LOCATION 0x001FFFFC
9
+
10
+typedef struct _BOOT_ARGS{
11
+	unsigned char ucVideoMode;
12
+	unsigned char ucComPort;
13
+	unsigned char ucBaudDivisor;
14
+	unsigned char ucPCIConfigType;
15
+	
16
+	unsigned long dwSig;
17
+	#define BOOTARG_SIG 0x544F4F42
18
+	unsigned long dwLen;
19
+	
20
+	unsigned char ucLoaderFlags;
21
+	unsigned char ucEshellFlags;
22
+	unsigned char ucEdbgAdapterType;
23
+	unsigned char ucEdbgIRQ;
24
+	
25
+	unsigned long dwEdbgBaseAddr;
26
+	unsigned long dwEdbgDebugZone;	
27
+	unsigned long dwDHCPLeaseTime;
28
+	unsigned long dwEdbgFlags;
29
+	
30
+	unsigned long dwEBootFlag;
31
+	unsigned long dwEBootAddr;
32
+	unsigned long dwLaunchAddr;
33
+	
34
+	unsigned long pvFlatFrameBuffer;
35
+	unsigned short vesaMode;
36
+	unsigned short cxDisplayScreen;
37
+	unsigned short cyDisplayScreen;
38
+	unsigned short cxPhysicalScreen;
39
+	unsigned short cyPhysicalScreen;
40
+	unsigned short cbScanLineLength;
41
+	unsigned short bppScreen;
42
+	
43
+	unsigned char RedMaskSize;
44
+	unsigned char REdMaskPosition;
45
+	unsigned char GreenMaskSize;
46
+	unsigned char GreenMaskPosition;
47
+	unsigned char BlueMaskSize;
48
+	unsigned char BlueMaskPosition;
49
+} BOOT_ARGS;
50
+
51
+BOOT_ARGS BootArgs;
52
+
53
+static struct segment_info{
54
+	unsigned long addr;		// Section Address
55
+	unsigned long size;		// Section Size
56
+	unsigned long checksum;		// Section CheckSum
57
+} X;
58
+
59
+#define PSIZE	(1500)			//Max Packet Size
60
+#define DSIZE  (PSIZE+12)
61
+static unsigned long dbuffer_available =0;
62
+static unsigned long not_loadin =0;
63
+static unsigned long d_now =0;
64
+
65
+unsigned long entry;
66
+static unsigned long ce_curaddr;
67
+
68
+
69
+static sector_t ce_loader(unsigned char *data, unsigned int len, int eof);
70
+static os_download_t wince_probe(unsigned char *data, unsigned int len)
71
+{
72
+	if (strncmp(ce_signature, data, sizeof(ce_signature)) != 0) {
73
+		return 0;
74
+	}
75
+	printf("(WINCE)");
76
+	return ce_loader;
77
+}
78
+
79
+static sector_t ce_loader(unsigned char *data, unsigned int len, int eof)
80
+{
81
+	static unsigned char dbuffer[DSIZE];
82
+	int this_write = 0;
83
+	static int firsttime = 1;
84
+
85
+	/*
86
+	 *	new packet in, we have to 
87
+	 *	[1] copy data to dbuffer,
88
+	 *
89
+	 *	update...
90
+	 *	[2]  dbuffer_available
91
+	 */
92
+	memcpy( (dbuffer+dbuffer_available), data, len);	//[1]
93
+	dbuffer_available += len;	// [2]
94
+	len = 0;
95
+
96
+	d_now = 0;
97
+	
98
+#if 0
99
+	printf("dbuffer_available =%ld \n", dbuffer_available);
100
+#endif 
101
+	
102
+	if (firsttime) 
103
+	{
104
+		d_now = sizeof(ce_signature);
105
+		printf("String Physical Address = %lx \n", 
106
+			*(unsigned long *)(dbuffer+d_now));
107
+		
108
+		d_now += sizeof(unsigned long);
109
+		printf("Image Size = %ld [%lx]\n", 
110
+			*(unsigned long *)(dbuffer+d_now), 
111
+			*(unsigned long *)(dbuffer+d_now));
112
+		
113
+		d_now += sizeof(unsigned long);
114
+		dbuffer_available -= d_now;			
115
+		
116
+		d_now = (unsigned long)get_x_header(dbuffer, d_now);
117
+		firsttime = 0;
118
+	}
119
+	
120
+	if (not_loadin == 0)
121
+	{
122
+		d_now = get_x_header(dbuffer, d_now);
123
+	}
124
+	
125
+	while ( not_loadin > 0 )
126
+	{
127
+		/* dbuffer do not have enough data to loading, copy all */
128
+#if LOAD_DEBUG
129
+		printf("[0] not_loadin = [%ld], dbuffer_available = [%ld] \n", 
130
+			not_loadin, dbuffer_available);
131
+		printf("[0] d_now = [%ld] \n", d_now);
132
+#endif
133
+		
134
+		if( dbuffer_available <= not_loadin)
135
+		{
136
+			this_write = dbuffer_available ;
137
+			memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write );
138
+			ce_curaddr += this_write;
139
+			not_loadin -= this_write;
140
+			
141
+			/* reset index and available in the dbuffer */
142
+			dbuffer_available = 0;
143
+			d_now = 0;
144
+#if LOAD_DEBUG
145
+			printf("[1] not_loadin = [%ld], dbuffer_available = [%ld] \n", 
146
+				not_loadin, dbuffer_available);
147
+			printf("[1] d_now = [%ld], this_write = [%d] \n", 
148
+				d_now, this_write);
149
+#endif
150
+				
151
+			// get the next packet...
152
+			return (0);
153
+		}
154
+			
155
+		/* dbuffer have more data then loading ... , copy partital.... */
156
+		else
157
+		{
158
+			this_write = not_loadin;
159
+			memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write);
160
+			ce_curaddr += this_write;
161
+			not_loadin = 0;
162
+			
163
+			/* reset index and available in the dbuffer */
164
+			dbuffer_available -= this_write;
165
+			d_now += this_write;
166
+#if LOAD_DEBUG
167
+			printf("[2] not_loadin = [%ld], dbuffer_available = [%ld] \n", 
168
+				not_loadin, dbuffer_available);
169
+			printf("[2] d_now = [%ld], this_write = [%d] \n\n", 
170
+				d_now, this_write);
171
+#endif
172
+			
173
+			/* dbuffer not empty, proceed processing... */
174
+			
175
+			// don't have enough data to get_x_header..
176
+			if ( dbuffer_available < (sizeof(unsigned long) * 3) )
177
+			{
178
+//				printf("we don't have enough data remaining to call get_x. \n");
179
+				memcpy( (dbuffer+0), (dbuffer+d_now), dbuffer_available);
180
+				return (0);
181
+			}
182
+			else
183
+			{
184
+#if LOAD_DEBUG				
185
+				printf("with remaining data to call get_x \n");
186
+				printf("dbuffer available = %ld , d_now = %ld\n", 
187
+					dbuffer_available, d_now);
188
+#endif					
189
+				d_now = get_x_header(dbuffer, d_now);
190
+			}
191
+		}
192
+	}
193
+	return (0);
194
+}
195
+
196
+static int get_x_header(unsigned char *dbuffer, unsigned long now)
197
+{
198
+	X.addr = *(unsigned long *)(dbuffer + now);
199
+	X.size = *(unsigned long *)(dbuffer + now + sizeof(unsigned long));
200
+	X.checksum = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)*2);
201
+
202
+	if (X.addr == 0)
203
+	{
204
+		entry = X.size;
205
+		done(1);
206
+		printf("Entry Point Address = [%lx] \n", entry);
207
+		jump_2ep();		
208
+	}
209
+
210
+	if (!prep_segment(X.addr, X.addr + X.size, X.addr + X.size, 0, 0)) {
211
+		longjmp(restart_etherboot, -2);
212
+	}
213
+
214
+	ce_curaddr = X.addr;
215
+	now += sizeof(unsigned long)*3;
216
+
217
+	/* re-calculate dbuffer available... */
218
+	dbuffer_available -= sizeof(unsigned long)*3;
219
+
220
+	/* reset index of this section */
221
+	not_loadin = X.size;
222
+	
223
+#if 1
224
+	printf("\n");
225
+	printf("\t Section Address = [%lx] \n", X.addr);
226
+	printf("\t Size = %d [%lx]\n", X.size, X.size);
227
+	printf("\t Checksum = %ld [%lx]\n", X.checksum, X.checksum);
228
+#endif
229
+#if LOAD_DEBUG
230
+	printf("____________________________________________\n");
231
+	printf("\t dbuffer_now = %ld \n", now);
232
+	printf("\t dbuffer available = %ld \n", dbuffer_available);
233
+	printf("\t not_loadin = %ld \n", not_loadin);
234
+#endif
235
+
236
+	return now;
237
+}
238
+
239
+static void jump_2ep()
240
+{
241
+	BootArgs.ucVideoMode = 1;
242
+	BootArgs.ucComPort = 1;
243
+	BootArgs.ucBaudDivisor = 1;
244
+	BootArgs.ucPCIConfigType = 1;	// do not fill with 0
245
+	
246
+	BootArgs.dwSig = BOOTARG_SIG;
247
+	BootArgs.dwLen = sizeof(BootArgs);
248
+	
249
+	if(BootArgs.ucVideoMode == 0)
250
+	{
251
+		BootArgs.cxDisplayScreen = 640;
252
+		BootArgs.cyDisplayScreen = 480;
253
+		BootArgs.cxPhysicalScreen = 640;
254
+		BootArgs.cyPhysicalScreen = 480;
255
+		BootArgs.bppScreen = 16;
256
+		BootArgs.cbScanLineLength  = 1024;
257
+		BootArgs.pvFlatFrameBuffer = 0x800a0000;	// ollie say 0x98000000
258
+	}	
259
+	else if(BootArgs.ucVideoMode != 0xFF)
260
+	{
261
+		BootArgs.cxDisplayScreen = 0;
262
+		BootArgs.cyDisplayScreen = 0;
263
+		BootArgs.cxPhysicalScreen = 0;
264
+		BootArgs.cyPhysicalScreen = 0;
265
+		BootArgs.bppScreen = 0;
266
+		BootArgs.cbScanLineLength  = 0;
267
+		BootArgs.pvFlatFrameBuffer = 0;	
268
+	}
269
+
270
+	ep = phys_to_virt(BOOT_ARG_PTR_LOCATION);
271
+	*ep= virt_to_phys(&BootArgs);
272
+	xstart32(entry);
273
+}

+ 1458
- 0
src/arch/i386/drivers/net/undi.c
File diff suppressed because it is too large
View File


+ 178
- 0
src/arch/i386/drivers/net/undi.h View File

@@ -0,0 +1,178 @@
1
+/**************************************************************************
2
+Etherboot -  BOOTP/TFTP Bootstrap Program
3
+UNDI NIC driver for Etherboot - header file
4
+
5
+This file Copyright (C) 2003 Michael Brown <mbrown@fensystems.co.uk>
6
+of Fen Systems Ltd. (http://www.fensystems.co.uk/).  All rights
7
+reserved.
8
+
9
+$Id$
10
+***************************************************************************/
11
+
12
+/*
13
+ * This program is free software; you can redistribute it and/or
14
+ * modify it under the terms of the GNU General Public License as
15
+ * published by the Free Software Foundation; either version 2, or (at
16
+ * your option) any later version.
17
+ */
18
+
19
+#include "pxe.h"
20
+#include "pic8259.h"
21
+
22
+/* A union that can function as the parameter block for any UNDI API call.
23
+ */
24
+typedef t_PXENV_ANY pxenv_structure_t;
25
+
26
+/* BIOS PnP parameter block.  We scan for this so that we can pass it
27
+ * to the UNDI driver.
28
+ */
29
+
30
+#define PNP_BIOS_SIGNATURE ( ('$'<<0) + ('P'<<8) + ('n'<<16) + ('P'<<24) )
31
+typedef struct pnp_bios {
32
+	uint32_t	signature;
33
+	uint8_t		version;
34
+	uint8_t		length;
35
+	uint16_t	control;
36
+	uint8_t		checksum;
37
+	uint8_t		dontcare[24];
38
+} PACKED pnp_bios_t;
39
+
40
+/* Structures within the PXE ROM.
41
+ */
42
+
43
+#define ROM_SIGNATURE 0xaa55
44
+typedef struct rom {
45
+	uint16_t	signature;
46
+	uint8_t		unused[0x14];
47
+	uint16_t	undi_rom_id_off;
48
+	uint16_t	pcir_off;
49
+	uint16_t	pnp_off;
50
+} PACKED rom_t;	
51
+
52
+#define PCIR_SIGNATURE ( ('P'<<0) + ('C'<<8) + ('I'<<16) + ('R'<<24) )
53
+typedef struct pcir_header {
54
+	uint32_t	signature;
55
+	uint16_t	vendor_id;
56
+	uint16_t	device_id;
57
+} PACKED pcir_header_t;
58
+
59
+#define PNP_SIGNATURE ( ('$'<<0) + ('P'<<8) + ('n'<<16) + ('P'<<24) )
60
+typedef struct pnp_header {
61
+	uint32_t	signature;
62
+	uint8_t		struct_revision;
63
+	uint8_t		length;
64
+	uint16_t	next;
65
+	uint8_t		reserved;
66
+	uint8_t		checksum;
67
+	uint16_t	id[2];
68
+	uint16_t	manuf_str_off;
69
+	uint16_t	product_str_off;
70
+	uint8_t		base_type;
71
+	uint8_t		sub_type;
72
+	uint8_t		interface_type;
73
+	uint8_t		indicator;
74
+	uint16_t	boot_connect_off;
75
+	uint16_t	disconnect_off;
76
+	uint16_t	initialise_off;
77
+	uint16_t	reserved2;
78
+	uint16_t	info;
79
+} PACKED pnp_header_t;
80
+
81
+#define UNDI_SIGNATURE ( ('U'<<0) + ('N'<<8) + ('D'<<16) + ('I'<<24) )
82
+typedef struct undi_rom_id {
83
+	uint32_t	signature;
84
+	uint8_t		struct_length;
85
+	uint8_t		struct_cksum;
86
+	uint8_t		struct_rev;
87
+	uint8_t		undi_rev[3];
88
+	uint16_t	undi_loader_off;
89
+	uint16_t	stack_size;
90
+	uint16_t	data_size;
91
+	uint16_t	code_size;
92
+} PACKED undi_rom_id_t;
93
+
94
+/* Nontrivial IRQ handler structure */
95
+typedef struct {
96
+	segoff_t		chain_to;
97
+	uint8_t			irq_chain, pad1, pad2, pad3;
98
+	segoff_t		entry;
99
+	uint16_t		count_all;
100
+	uint16_t		count_ours;
101
+	t_PXENV_UNDI_ISR	undi_isr;
102
+	char			code[0];
103
+} PACKED undi_irq_handler_t ;
104
+
105
+/* Storage buffers that we need in base memory.  We collect these into
106
+ * a single structure to make allocation simpler.
107
+ */
108
+
109
+typedef struct undi_base_mem_xmit_data {
110
+	MAC_ADDR		destaddr;
111
+	t_PXENV_UNDI_TBD	tbd;
112
+} undi_base_mem_xmit_data_t;
113
+
114
+typedef struct undi_base_mem_data {
115
+	pxenv_structure_t	pxs;
116
+	undi_base_mem_xmit_data_t xmit_data;
117
+	char			xmit_buffer[ETH_FRAME_LEN];
118
+	/* Must be last in structure and paragraph-aligned */
119
+	union {
120
+		char			e820mangler[0];
121
+		char			irq_handler[0];
122
+		undi_irq_handler_t	nontrivial_irq_handler;
123
+	}  __attribute__ ((aligned(16)));
124
+} undi_base_mem_data_t;
125
+
126
+/* Macros and data structures used when freeing bits of base memory
127
+ * used by the UNDI driver.
128
+ */
129
+
130
+#define FIRING_SQUAD_TARGET_SIZE 8
131
+#define FIRING_SQUAD_TARGET_INDEX(x) ( (x) / FIRING_SQUAD_TARGET_SIZE )
132
+#define FIRING_SQUAD_TARGET_BIT(x) ( (x) % FIRING_SQUAD_TARGET_SIZE )
133
+typedef struct firing_squad_lineup {
134
+	uint8_t targets[ 640 / FIRING_SQUAD_TARGET_SIZE ];
135
+} firing_squad_lineup_t;
136
+typedef enum firing_squad_shoot {
137
+	DONTSHOOT = 0,
138
+	SHOOT = 1
139
+} firing_squad_shoot_t;
140
+
141
+/* Driver private data structure.
142
+ */
143
+
144
+typedef struct undi {
145
+	/* Pointers to various data structures */
146
+	pnp_bios_t		*pnp_bios;
147
+	rom_t			*rom;
148
+	undi_rom_id_t		*undi_rom_id;
149
+	pxe_t			*pxe;
150
+	pxenv_structure_t	*pxs;
151
+	undi_base_mem_xmit_data_t *xmit_data;
152
+	/* Pointers and sizes to keep track of allocated base memory */
153
+	undi_base_mem_data_t	*base_mem_data;
154
+	void			*driver_code;
155
+	size_t			driver_code_size;
156
+	void			*driver_data;
157
+	size_t			driver_data_size;
158
+	char			*xmit_buffer;
159
+	/* Flags.  We keep our own instead of trusting the UNDI driver
160
+	 * to have implemented PXENV_UNDI_GET_STATE correctly.  Plus
161
+	 * there's the small issue of PXENV_UNDI_GET_STATE being the
162
+	 * same API call as PXENV_STOP_UNDI...
163
+	 */
164
+	uint8_t prestarted;	/* pxenv_start_undi() has been called */
165
+	uint8_t started;	/* pxenv_undi_startup() has been called */
166
+	uint8_t	initialized;	/* pxenv_undi_initialize() has been called */
167
+	uint8_t opened;		/* pxenv_undi_open() has been called */
168
+	/* Parameters that we need to store for future reference
169
+	 */
170
+	struct pci_device	pci;
171
+	irq_t			irq;
172
+} undi_t;
173
+
174
+/* Constants
175
+ */
176
+
177
+#define HUNT_FOR_PIXIES 0
178
+#define HUNT_FOR_UNDI_ROMS 1

+ 317
- 0
src/arch/i386/firmware/pcbios/basemem.c View File

@@ -0,0 +1,317 @@
1
+#ifdef PCBIOS
2
+
3
+#include "etherboot.h"
4
+#include "realmode.h" /* for real_mode_stack */
5
+
6
+/* Routines to allocate base memory in a BIOS-compatible way, by
7
+ * updating the Free Base Memory Size counter at 40:13h.
8
+ *
9
+ * Michael Brown <mbrown@fensystems.co.uk> (mcb30)
10
+ * $Id$
11
+ */
12
+
13
+#define fbms ( ( uint16_t * ) phys_to_virt ( 0x413 ) )
14
+#define BASE_MEMORY_MAX ( 640 )
15
+#define FREE_BLOCK_MAGIC ( ('!'<<0) + ('F'<<8) + ('R'<<16) + ('E'<<24) )
16
+#define FREE_BASE_MEMORY ( (uint32_t) ( *fbms << 10 ) )
17
+
18
+/* Prototypes */
19
+void * _allot_base_memory ( size_t size );
20
+void _forget_base_memory ( void *ptr, size_t size );
21
+
22
+typedef struct free_base_memory_block {
23
+	uint32_t	magic;
24
+	uint16_t	size_kb;
25
+} free_base_memory_block_t;
26
+
27
+/* Return amount of free base memory in bytes
28
+ */
29
+
30
+uint32_t get_free_base_memory ( void ) {
31
+	return FREE_BASE_MEMORY;
32
+}
33
+
34
+/* Start of our image in base memory.
35
+ */
36
+#define __text16_nocompress __attribute__ ((section (".text16.nocompress")))
37
+uint32_t image_basemem __text16_nocompress = 0;
38
+uint32_t image_basemem_size __text16_nocompress = 0;
39
+
40
+/* Allot/free the real-mode stack
41
+ */
42
+
43
+void allot_real_mode_stack ( void )
44
+{
45
+	void *new_real_mode_stack;
46
+
47
+	if ( lock_real_mode_stack ) 
48
+		return;
49
+
50
+	/* This is evil hack. 
51
+	 * Until we have a real_mode stack use 0x7c00.
52
+	 * Except for 0 - 0x600 membory below 0x7c00 is hardly every used.
53
+	 * This stack should never be used unless the stack allocation fails,
54
+	 * or if someone has placed a print statement in a dangerous location.
55
+	 */
56
+	if (!real_mode_stack) {
57
+		real_mode_stack = 0x7c00;
58
+	}
59
+	new_real_mode_stack = _allot_base_memory ( real_mode_stack_size );
60
+	if ( ! new_real_mode_stack ) {
61
+		printf ( "FATAL: No real-mode stack\n" );
62
+		while ( 1 ) {};
63
+	}
64
+	real_mode_stack = virt_to_phys ( new_real_mode_stack );
65
+	get_memsizes();
66
+}
67
+
68
+void forget_real_mode_stack ( void )
69
+{
70
+	if ( lock_real_mode_stack ) 
71
+		return;
72
+
73
+	if ( real_mode_stack) {
74
+		_forget_base_memory ( phys_to_virt(real_mode_stack),
75
+				      real_mode_stack_size );
76
+		/* get_memsizes() uses the real_mode stack we just freed
77
+		 * for it's BIOS calls.
78
+		 */
79
+		get_memsizes();
80
+		real_mode_stack = 0;
81
+	}
82
+}
83
+
84
+/* Allocate N bytes of base memory.  Amount allocated will be rounded
85
+ * up to the nearest kB, since that's the granularity of the BIOS FBMS
86
+ * counter.  Returns NULL if memory cannot be allocated.
87
+ */
88
+
89
+static void * _allot_base_memory ( size_t size ) 
90
+{
91
+	uint16_t size_kb = ( size + 1023 ) >> 10;
92
+	void *ptr = NULL;
93
+
94
+#ifdef DEBUG_BASEMEM
95
+	printf ( "Trying to allocate %d kB of base memory from %d kB free\n",
96
+		 size_kb, *fbms );
97
+#endif
98
+
99
+	/* Free up any unused memory before we start */
100
+	free_unused_base_memory();
101
+
102
+	/* Check available base memory */
103
+	if ( size_kb > *fbms ) { return NULL; }
104
+
105
+	/* Reduce available base memory */
106
+	*fbms -= size_kb;
107
+
108
+	/* Calculate address of memory allocated */
109
+	ptr = phys_to_virt ( FREE_BASE_MEMORY );
110
+
111
+	/* Zero out memory.  We do this so that allocation of
112
+	 * already-used space will show up in the form of a crash as
113
+	 * soon as possible.
114
+	 *
115
+	 * Update: there's another reason for doing this.  If we don't
116
+	 * zero the contents, then they could still retain our "free
117
+	 * block" markers and be liable to being freed whenever a
118
+	 * base-memory allocation routine is next called.
119
+	 */
120
+	memset ( ptr, 0, size_kb << 10 );
121
+
122
+#ifdef DEBUG_BASEMEM
123
+	printf ( "Allocated %d kB at [%x,%x)\n", size_kb,
124
+		 virt_to_phys ( ptr ),
125
+		 virt_to_phys ( ptr ) + size_kb * 1024 );
126
+#endif
127
+
128
+	return ptr;
129
+}
130
+
131
+void * allot_base_memory ( size_t size )
132
+{
133
+	void *ptr;
134
+
135
+	/* Free real-mode stack, allocate memory, reallocate real-mode
136
+	 * stack.
137
+	 */
138
+	forget_real_mode_stack();
139
+	ptr = _allot_base_memory ( size );
140
+	get_memsizes();
141
+	return ptr;
142
+}
143
+
144
+/* Free base memory allocated by allot_base_memory.  The BIOS provides
145
+ * nothing better than a LIFO mechanism for freeing memory (i.e. it
146
+ * just has the single "total free memory" counter), but we improve
147
+ * upon this slightly; as long as you free all the allotted blocks, it
148
+ * doesn't matter what order you free them in.  (This will only work
149
+ * for blocks that are freed via forget_base_memory()).
150
+ *
151
+ * Yes, it's annoying that you have to remember the size of the blocks
152
+ * you've allotted.  However, since our granularity of allocation is
153
+ * 1K, the alternative is to risk wasting the occasional kB of base
154
+ * memory, which is a Bad Thing.  Really, you should be using as
155
+ * little base memory as possible, so consider the awkwardness of the
156
+ * API to be a feature! :-)
157
+ */
158
+
159
+static void _forget_base_memory ( void *ptr, size_t size ) 
160
+{
161
+	uint16_t remainder = virt_to_phys(ptr) & 1023;
162
+	uint16_t size_kb = ( size + remainder + 1023 ) >> 10;
163
+	free_base_memory_block_t *free_block =
164
+		( free_base_memory_block_t * ) ( ptr - remainder );
165
+	
166
+	if ( ( ptr == NULL ) || ( size == 0 ) ) { 
167
+		return; 
168
+	}
169
+
170
+#ifdef DEBUG_BASEMEM
171
+	printf ( "Trying to free %d bytes base memory at 0x%x\n",
172
+		 size, virt_to_phys ( ptr ) );
173
+	if ( remainder > 0 ) {
174
+		printf ( "WARNING: destructively expanding free block "
175
+			 "downwards to 0x%x\n",
176
+			 virt_to_phys ( ptr - remainder ) );
177
+	}
178
+#endif
179
+
180
+	/* Mark every kilobyte within this block as free.  This is
181
+	 * overkill for normal purposes, but helps when something has
182
+	 * allocated base memory with a granularity finer than the
183
+	 * BIOS granularity of 1kB.  PXE ROMs tend to do this when
184
+	 * they allocate their own memory.  This method allows us to
185
+	 * free their blocks (admittedly in a rather dangerous,
186
+	 * tread-on-anything-either-side sort of way, but there's no
187
+	 * other way to do it).
188
+	 *
189
+	 * Since we're marking every kB as free, there's actually no
190
+	 * need for recording the size of the blocks.  However, we
191
+	 * keep this in so that debug messages are friendlier.  It
192
+	 * probably adds around 8 bytes to the overall code size.
193
+	 */
194
+	while ( size_kb > 0 ) {
195
+		/* Mark this block as unused */
196
+		free_block->magic = FREE_BLOCK_MAGIC;
197
+		free_block->size_kb = size_kb;
198
+		/* Move up by 1 kB */
199
+		free_block = (void *)(((char *)free_block) + (1 << 10));
200
+		size_kb--;
201
+	}
202
+
203
+	/* Free up unused base memory */
204
+	free_unused_base_memory();
205
+}
206
+
207
+void forget_base_memory ( void *ptr, size_t size )
208
+{
209
+	/* Free memory, free real-mode stack, re-allocate real-mode
210
+	 * stack.  Do this so that we don't end up wasting a huge
211
+	 * block of memory trapped behind the real-mode stack.
212
+	 */
213
+	_forget_base_memory ( ptr, size );
214
+	forget_real_mode_stack();
215
+	get_memsizes();
216
+}
217
+
218
+/* Do the actual freeing of memory.  This is split out from
219
+ * forget_base_memory() so that it may be called separately.  It
220
+ * should be called whenever base memory is deallocated by an external
221
+ * entity (if we can detect that it has done so) so that we get the
222
+ * chance to free up our own blocks.
223
+ */
224
+static void free_unused_base_memory ( void ) {
225
+	free_base_memory_block_t *free_block = NULL;
226
+
227
+	/* Try to release memory back to the BIOS.  Free all
228
+	 * consecutive blocks marked as free.
229
+	 */
230
+	while ( 1 ) {
231
+		/* Calculate address of next potential free block */
232
+		free_block = ( free_base_memory_block_t * )
233
+			phys_to_virt ( FREE_BASE_MEMORY );
234
+		
235
+		/* Stop processing if we're all the way up to 640K or
236
+		 * if this is not a free block
237
+		 */
238
+		if ( ( *fbms == BASE_MEMORY_MAX ) ||
239
+		     ( free_block->magic != FREE_BLOCK_MAGIC ) ) {
240
+			break;
241
+		}
242
+
243
+		/* Return memory to BIOS */
244
+		*fbms += free_block->size_kb;
245
+
246
+#ifdef DEBUG_BASEMEM
247
+		printf ( "Freed %d kB base memory, %d kB now free\n",
248
+			 free_block->size_kb, *fbms );
249
+#endif
250
+		
251
+		/* Zero out freed block.  We do this in case
252
+		 * the block contained any structures that
253
+		 * might be located by scanning through
254
+		 * memory.
255
+		 */
256
+		memset ( free_block, 0, free_block->size_kb << 10 );
257
+	}
258
+}
259
+
260
+/* Free base memory used by the prefix.  Called once at start of
261
+ * Etherboot by arch_main().
262
+ */
263
+void forget_prefix_base_memory ( void )
264
+{
265
+	/* runtime_start_kb is _text rounded down to a physical kB boundary */
266
+	uint32_t runtime_start_kb = virt_to_phys(_text) & ~0x3ff;
267
+	/* prefix_size_kb is the prefix size excluding any portion
268
+	 * that overlaps into the first kB used by the runtime image
269
+	 */
270
+	uint32_t prefix_size_kb = runtime_start_kb - image_basemem;
271
+
272
+#ifdef DEBUG_BASEMEM
273
+	printf ( "Attempting to free base memory used by prefix\n" );
274
+#endif
275
+
276
+	/* If the decompressor is in allocated base memory
277
+	 * *and* the Etherboot text is in base
278
+	 * memory, then free the decompressor.
279
+	 */
280
+	if ( ( image_basemem >= FREE_BASE_MEMORY ) &&
281
+	     ( runtime_start_kb >= FREE_BASE_MEMORY ) &&
282
+	     ( runtime_start_kb <= ( BASE_MEMORY_MAX << 10 ) ) ) 
283
+	{
284
+		forget_base_memory ( phys_to_virt ( image_basemem ),
285
+				     prefix_size_kb );
286
+		/* Update image_basemem and image_basemem_size to
287
+		 * indicate that our allocation now starts with _text
288
+		 */
289
+		image_basemem = runtime_start_kb;
290
+		image_basemem_size -= prefix_size_kb;
291
+	}
292
+}
293
+
294
+/* Free base memory used by the runtime image.  Called after
295
+ * relocation by arch_relocated_from().
296
+ */
297
+void forget_runtime_base_memory ( unsigned long old_addr )
298
+{
299
+	/* text_start_kb is old _text rounded down to a physical KB boundary */
300
+	uint32_t old_text_start_kb = old_addr & ~0x3ff;
301
+
302
+#ifdef DEBUG_BASEMEM
303
+	printf ( "Attempting to free base memory used by runtime image\n" );
304
+#endif
305
+
306
+	if ( ( image_basemem >= FREE_BASE_MEMORY ) &&
307
+	     ( image_basemem == old_text_start_kb ) ) 
308
+	{
309
+		forget_base_memory ( phys_to_virt ( image_basemem ),
310
+				     image_basemem_size );
311
+		/* Update image_basemem to show no longer in use */
312
+		image_basemem = 0;
313
+		image_basemem_size = 0;
314
+	}
315
+}
316
+
317
+#endif /* PCBIOS */

+ 155
- 0
src/arch/i386/firmware/pcbios/bios.c View File

@@ -0,0 +1,155 @@
1
+/* Etherboot routines for PCBIOS firmware.
2
+ *
3
+ * Body of routines taken from old pcbios.S
4
+ */
5
+
6
+#ifdef PCBIOS
7
+
8
+#include "etherboot.h"
9
+#include "realmode.h"
10
+#include "segoff.h"
11
+
12
+#define CF ( 1 << 0 )
13
+
14
+/**************************************************************************
15
+CURRTICKS - Get Time
16
+Use direct memory access to BIOS variables, longword 0040:006C (ticks
17
+today) and byte 0040:0070 (midnight crossover flag) instead of calling
18
+timeofday BIOS interrupt.
19
+**************************************************************************/
20
+#if defined(CONFIG_TSC_CURRTICKS)
21
+#undef CONFIG_BIOS_CURRTICKS
22
+#else
23
+#define CONFIG_BIOS_CURRTICKS 1
24
+#endif
25
+#if defined(CONFIG_BIOS_CURRTICKS)
26
+unsigned long currticks (void) 
27
+{
28
+	static uint32_t days = 0;
29
+	uint32_t *ticks = VIRTUAL(0x0040,0x006c);
30
+	uint8_t *midnight = VIRTUAL(0x0040,0x0070);
31
+
32
+	/* Re-enable interrupts so that the timer interrupt can occur
33
+	 */
34
+	RM_FRAGMENT(rm_currticks,
35
+		"sti\n\t"
36
+		"nop\n\t"
37
+		"nop\n\t"
38
+		"cli\n\t"
39
+	);	
40
+
41
+	real_call ( rm_currticks, NULL, NULL );
42
+
43
+	if ( *midnight ) {
44
+		*midnight = 0;
45
+		days += 0x1800b0;
46
+	}
47
+	return ( days + *ticks );
48
+}
49
+#endif	/* CONFIG_BIOS_CURRTICKS */
50
+
51
+/**************************************************************************
52
+INT15 - Call Interrupt 0x15
53
+**************************************************************************/
54
+int int15 ( int ax )
55
+{
56
+	struct {
57
+		reg16_t ax;
58
+	} PACKED in_stack;
59
+	struct {
60
+		reg16_t flags;
61
+	} PACKED out_stack;
62
+	reg16_t ret_ax;
63
+
64
+	RM_FRAGMENT(rm_int15,
65
+		"sti\n\t"
66
+		"popw %ax\n\t"
67
+		"stc\n\t"
68
+		"int $0x15\n\t"
69
+		"pushf\n\t"
70
+		"cli\n\t"
71
+	);
72
+
73
+	in_stack.ax.word = ax;
74
+	ret_ax.word = real_call ( rm_int15, &in_stack, &out_stack );
75
+
76
+	/* Carry flag clear indicates function not supported */
77
+	if ( ! ( out_stack.flags.word & CF ) ) return 0;
78
+	return ret_ax.h;
79
+}
80
+
81
+#ifdef	POWERSAVE
82
+/**************************************************************************
83
+CPU_NAP - Save power by halting the CPU until the next interrupt
84
+**************************************************************************/
85
+void cpu_nap ( void )
86
+{
87
+	RM_FRAGMENT(rm_cpu_nap,
88
+		"sti\n\t"
89
+		"hlt\n\t"
90
+		"cli\n\t"
91
+	);	
92
+
93
+	real_call ( rm_cpu_nap, NULL, NULL );
94
+}
95
+#endif	/* POWERSAVE */
96
+
97
+#if	(TRY_FLOPPY_FIRST > 0)
98
+/**************************************************************************
99
+DISK_INIT - Initialize the disk system
100
+**************************************************************************/
101
+void disk_init ( void )
102
+{
103
+	RM_FRAGMENT(rm_disk_init,
104
+		"sti\n\t"
105
+		"xorw %ax,%ax\n\t"
106
+		"movb $0x80,%dl\n\t"
107
+		"int $0x13\n\t"
108
+		"cli\n\t"
109
+	);
110
+	
111
+	real_call ( rm_disk_init, NULL, NULL );
112
+}
113
+
114
+/**************************************************************************
115
+DISK_READ - Read a sector from disk
116
+**************************************************************************/
117
+unsigned int pcbios_disk_read ( int drive, int cylinder, int head, int sector,
118
+				char *buf ) {
119
+	struct {
120
+		reg16_t ax;
121
+		reg16_t cx;
122
+		reg16_t dx;
123
+		segoff_t buffer;
124
+	} PACKED in_stack;
125
+	struct {
126
+		reg16_t flags;
127
+	} PACKED out_stack;
128
+	reg16_t ret_ax;
129
+
130
+	RM_FRAGMENT(rm_pcbios_disk_read,
131
+		"sti\n\t"
132
+		"popw %ax\n\t"
133
+		"popw %cx\n\t"
134
+		"popw %dx\n\t"
135
+		"popw %bx\n\t"
136
+		"popw %es\n\t"
137
+		"int $0x13\n\t"
138
+		"pushfw\n\t"
139
+		"cli\n\t"
140
+	);
141
+
142
+	in_stack.ax.h = 2; /* INT 13,2 - Read disk sector */
143
+	in_stack.ax.l = 1; /* Read one sector */
144
+	in_stack.cx.h = cylinder & 0xff;
145
+	in_stack.cx.l = ( ( cylinder >> 8 ) & 0x3 ) | sector;
146
+	in_stack.dx.h = head;
147
+	in_stack.dx.l = drive;
148
+	in_stack.buffer.segment = SEGMENT ( buf );
149
+	in_stack.buffer.offset = OFFSET ( buf );
150
+	ret_ax.word = real_call ( rm_pcbios_disk_read, &in_stack, &out_stack );
151
+	return ( out_stack.flags.word & CF ) ? ret_ax.word : 0;
152
+}
153
+#endif /* TRY_FLOPPY_FIRST */
154
+
155
+#endif /* PCBIOS */

+ 85
- 0
src/arch/i386/firmware/pcbios/console.c View File

@@ -0,0 +1,85 @@
1
+/* Etherboot routines for PCBIOS firmware.
2
+ *
3
+ * Body of routines taken from old pcbios.S
4
+ */
5
+
6
+#ifdef PCBIOS
7
+
8
+#include "etherboot.h"
9
+#include "realmode.h"
10
+#include "segoff.h"
11
+
12
+#define ZF ( 1 << 6 )
13
+
14
+/**************************************************************************
15
+CONSOLE_PUTC - Print a character on console
16
+**************************************************************************/
17
+void console_putc ( int character )
18
+{
19
+	struct {
20
+		reg16_t ax;
21
+	} PACKED in_stack;
22
+
23
+	RM_FRAGMENT(rm_console_putc,
24
+		"sti\n\t"
25
+		"popw %ax\n\t"
26
+		"movb $0x0e, %ah\n\t"
27
+		"movl $1, %ebx\n\t"
28
+		"int $0x10\n\t"
29
+		"cli\n\t"
30
+	);
31
+
32
+	in_stack.ax.l = character;
33
+	real_call ( rm_console_putc, &in_stack, NULL );
34
+}
35
+
36
+/**************************************************************************
37
+CONSOLE_GETC - Get a character from console
38
+**************************************************************************/
39
+int console_getc ( void )
40
+{
41
+	RM_FRAGMENT(rm_console_getc,
42
+		"sti\n\t"
43
+		"xorw %ax, %ax\n\t"
44
+		"int $0x16\n\t"
45
+		"xorb %ah, %ah\n\t"
46
+		"cli\n\t"
47
+	);	
48
+
49
+	return real_call ( rm_console_getc, NULL, NULL );
50
+}
51
+
52
+/**************************************************************************
53
+CONSOLE_ISCHAR - Check for keyboard interrupt
54
+**************************************************************************/
55
+int console_ischar ( void )
56
+{
57
+	RM_FRAGMENT(rm_console_ischar,
58
+		"sti\n\t"
59
+		"movb $1, %ah\n\t"
60
+		"int $0x16\n\t"
61
+		"pushfw\n\t"
62
+		"popw %ax\n\t"
63
+		"cli\n\t"
64
+	);
65
+
66
+	return ( ( real_call ( rm_console_ischar, NULL, NULL ) & ZF ) == 0 );
67
+}
68
+
69
+/**************************************************************************
70
+GETSHIFT - Get keyboard shift state
71
+**************************************************************************/
72
+int getshift ( void )
73
+{
74
+	RM_FRAGMENT(rm_getshift,
75
+		"sti\n\t"
76
+		"movb $2, %ah\n\t"
77
+		"int $0x16\n\t"
78
+		"andw $0x3, %ax\n\t" 
79
+		"cli\n\t"
80
+	);
81
+
82
+	return real_call ( rm_getshift, NULL, NULL );
83
+}
84
+
85
+#endif /* PCBIOS */

+ 296
- 0
src/arch/i386/firmware/pcbios/e820mangler.S View File

@@ -0,0 +1,296 @@
1
+#undef CODE16
2
+#if defined(PCBIOS)
3
+#define	CODE16
4
+#endif
5
+
6
+#ifdef CODE16
7
+	
8
+#define BOCHSBP xchgw %bx,%bx
9
+	
10
+	.text
11
+	.arch i386
12
+	.section ".text16", "ax", @progbits
13
+	.code16
14
+
15
+/****************************************************************************
16
+ * Memory map mangling code
17
+ ****************************************************************************
18
+ */
19
+
20
+	.globl	e820mangler
21
+e820mangler:
22
+
23
+/* Macro to calculate offset of labels within code segment in
24
+ * installed copy of code.
25
+ */
26
+#define INSTALLED(x) ( (x) - e820mangler )
27
+	
28
+/****************************************************************************
29
+ * Intercept INT 15 memory calls and remove the hidden memory ranges
30
+ * from the resulting memory map.
31
+ ****************************************************************************
32
+ */
33
+	.globl	_intercept_int15
34
+_intercept_int15:
35
+	/* Preserve registers */
36
+	pushw	%bp
37
+	/* Store %ax for future reference */
38
+	pushw	%ax
39
+	/* Make INT-style call to old INT15 routine */
40
+	pushfw
41
+	lcall	%cs:*INSTALLED(_intercepted_int15)
42
+	/* Preserve flags returned by original E820 routine */
43
+	pushfw
44
+	/* Check for valid INT15 routine */
45
+	jc	intercept_int15_exit
46
+	/* Check for a routine we want to intercept */
47
+	movw	%sp, %bp
48
+	cmpw	$0xe820, 2(%bp)
49
+	je	intercept_e820
50
+	cmpw	$0xe801, 2(%bp)
51
+	je	intercept_e801
52
+	cmpb	$0x88, 3(%bp)
53
+	je	intercept_88
54
+intercept_int15_exit:
55
+	/* Restore registers and return */
56
+	popfw
57
+	popw	%bp			/* discard original %ax */
58
+	popw	%bp
59
+	lret	$2			/* 'iret' - flags already loaded */
60
+
61
+	.globl	_intercepted_int15
62
+_intercepted_int15:	.word 0,0
63
+		
64
+/****************************************************************************
65
+ * Exclude an address range from a potentially overlapping address range
66
+ *
67
+ * Note: this *can* be called even if the range doesn't overlap; it
68
+ * will simply return the range unaltered.  It copes with all the
69
+ * possible cases of overlap, including total overlap (which will
70
+ * modify the range to length zero).  If the to-be-excluded range is
71
+ * in the middle of the target range, then the larger remaining
72
+ * portion will be returned.  If %di is nonzero on entry then the
73
+ * range will only be truncated from the high end, i.e. the base
74
+ * address will never be altered.  All this in less than 30
75
+ * instructions.  :)
76
+ *
77
+ * Parameters:
78
+ *  %eax	Base address of memory range
79
+ *  %ecx	Length of memory range
80
+ *  %ebx	Base address of memory range to exclude
81
+ *  %edx	Length of memory range to exclude
82
+ *  %di		0 => truncate either end, 1 => truncate high end only
83
+ * Returns:
84
+ *  %eax	Updated base address of range
85
+ *  %ecx	Updated length of range
86
+ *  %ebx,%edx	Undefined
87
+ *		All other registers (including %di) preserved
88
+ *
89
+ * Note: "ja" is used rather than "jg" because we are comparing
90
+ * unsigned ints
91
+ ****************************************************************************
92
+ */
93
+#ifdef TEST_EXCLUDE_ALGORITHM
94
+	.code32
95
+#endif /* TEST_EXCLUDE_ALGORITHM */
96
+exclude_memory_range:
97
+	/* Convert (start,length) to (start,end) */
98
+	addl	%eax, %ecx
99
+	addl	%ebx, %edx
100
+	/* Calculate "prefix" length */
101
+	subl	%eax, %ebx		/* %ebx = "prefix" length */
102
+	ja	1f
103
+	xorl	%ebx, %ebx		/* Truncate to zero if negative */
104
+1:	/* %di == 0 => truncate either end
105
+	 * %di != 0 => truncate only high end
106
+	 */
107
+	testw	%di, %di
108
+	je	use_either
109
+	cmpl	%eax, %edx
110
+	jbe	99f			/* excl. range is below target range */
111
+use_prefix:	/* Use prefix, discard suffix */
112
+	addl	%eax, %ebx		/* %ebx = candidate end address */
113
+	cmpl	%ecx, %ebx		/* %ecx = min ( %ebx, %ecx ) */
114
+	ja	1f
115
+	movl	%ebx, %ecx
116
+1:	jmp	99f
117
+use_either:		
118
+	/* Calculate "suffix" length */
119
+	subl	%ecx, %edx		/* %edx = -( "suffix" length ) */
120
+	jb	1f
121
+	xorl	%edx, %edx		/* Truncate to zero if negative */
122
+1:	negl	%edx			/* %edx = "suffix" length */
123
+	/* Use whichever is longest of "prefix" and "suffix" */
124
+	cmpl	%ebx, %edx
125
+	jbe	use_prefix
126
+use_suffix:	/* Use suffix, discard prefix */
127
+	negl	%edx
128
+	addl	%ecx, %edx		/* %edx = candidate start address */
129
+	cmpl	%eax, %edx		/* %eax = max ( %eax, %edx ) */
130
+	jb	1f
131
+	movl	%edx, %eax
132
+1:	
133
+99:	subl	%eax, %ecx		/* Convert back to (start,length) */
134
+	ret
135
+
136
+#ifdef TEST_EXCLUDE_ALGORITHM
137
+	.globl	__test_exclude
138
+__test_exclude:
139
+	pushl   %ebx
140
+	pushl	%edi
141
+	movl    12(%esp), %eax
142
+	movl    16(%esp), %ecx
143
+	movl    20(%esp), %ebx
144
+	movl    24(%esp), %edx
145
+	movl	28(%esp), %edi
146
+	call    exclude_memory_range
147
+	shll    $16, %eax
148
+	orl     %ecx, %eax
149
+	popl	%edi
150
+	popl	%ebx
151
+	ret
152
+	.code16
153
+#endif /* TEST_EXCLUDE_ALGORITHM */
154
+	
155
+/****************************************************************************
156
+ * Exclude Etherboot-reserved address ranges from a potentially
157
+ * overlapping address range
158
+ *
159
+ * Parameters:
160
+ *  %eax	Base address of memory range
161
+ *  %ecx	Length of memory range
162
+ *  %di		0 => truncate either end, 1 => truncate high end only
163
+ * Returns:
164
+ *  %eax	Updated base address of range
165
+ *  %ecx	Updated length of range
166
+ *		All other registers (including %di) preserved
167
+ ****************************************************************************
168
+ */
169
+exclude_hidden_memory_ranges:
170
+	pushw	%si
171
+	pushl	%ebx
172
+	pushl	%edx
173
+	movw	$INSTALLED(_hide_memory), %si
174
+2:	movl	%cs:0(%si), %ebx
175
+	movl	%cs:4(%si), %edx
176
+	call	exclude_memory_range
177
+	addw	$8, %si
178
+	cmpw	$INSTALLED(_hide_memory_end), %si
179
+	jl	2b
180
+	popl	%edx
181
+	popl	%ebx
182
+	popw	%si
183
+	ret
184
+	
185
+	.globl	_hide_memory	
186
+_hide_memory:
187
+	.long	0,0			/* Etherboot text (base,length) */
188
+	.long	0,0			/* Heap (base,length) */
189
+_hide_memory_end:
190
+
191
+/****************************************************************************
192
+ * Intercept INT 15,E820 calls and remove the hidden memory ranges
193
+ * from the resulting memory map.
194
+ ****************************************************************************
195
+ */
196
+#define SMAP ( 0x534d4150 )
197
+intercept_e820:
198
+	/* Check for valid E820 routine */
199
+	cmpl	$SMAP, %eax
200
+	jne	intercept_int15_exit
201
+	/* If base address isn't in the low 4GB, return unaltered
202
+	 * (since we never claim memory above 4GB).  WARNING: we cheat
203
+	 * by assuming that no E820 region will straddle the 4GB
204
+	 * boundary: if this is not a valid assumption then things
205
+	 * will probably break.
206
+	 */
207
+	cmpl	$0, %es:4(%di)
208
+	jne	intercept_int15_exit
209
+	/* Preserve registers */
210
+	pushl	%eax
211
+	pushl	%ecx
212
+	/* Update returned memory range */
213
+	movl	%es:0(%di), %eax	/* Base */
214
+	movl	%es:8(%di), %ecx	/* Length */
215
+	pushw	%di
216
+	xorw	%di, %di		/* "truncate either end" flag */
217
+	call	exclude_hidden_memory_ranges
218
+	popw	%di
219
+	movl	%eax, %es:0(%di)	/* Store updated base */
220
+	movl	%ecx, %es:8(%di)	/* Store updated length */
221
+	/* Restore registers and return */
222
+	popl	%ecx
223
+	popl	%eax
224
+	jmp	intercept_int15_exit
225
+
226
+/****************************************************************************
227
+ * Intercept INT 15,E801 calls and remove the hidden memory ranges
228
+ * from the resulting memory map.
229
+ ****************************************************************************
230
+ */
231
+intercept_e801:
232
+	/* Adjust return values */
233
+	call	e801_adjust
234
+	xchgw	%ax, %cx
235
+	xchgw	%bx, %dx
236
+	call	e801_adjust
237
+	xchgw	%ax, %cx
238
+	xchgw	%bx, %dx
239
+	jmp	intercept_int15_exit
240
+	
241
+	/* %ax = #KB from 1MB+, %bx = #64KB from 16MB+
242
+	 * Return with modified values in %ax, %bx.  Preserver other regs.
243
+	 */
244
+e801_adjust:
245
+	pushw	%di
246
+	pushl	%ecx
247
+	pushl	%eax
248
+	movw	$1, %di			/* "truncate only high end" flag */
249
+
250
+	/* Truncate #64KB from 16MB+ as appropriate */
251
+	movw	%bx, %cx		/* (no need to zero high word) */
252
+	shll	$16, %ecx		/* %ecx = length in bytes */
253
+	movl	$(1<<24), %eax		/* 16MB start address */
254
+	call	exclude_hidden_memory_ranges
255
+	shrl	$16, %ecx		/* %cx = updated length in 64KB */
256
+	movw	%cx, %bx		/* Return in %bx */
257
+	
258
+	/* Truncate #KB from 1MB+ as appropriate */
259
+	popw	%cx			/* Orig. %ax (high word already 0) */
260
+	shll	$10, %ecx		/* %ecx = length in bytes */
261
+	shrl	$4, %eax		/* 1MB start address */
262
+	call	exclude_hidden_memory_ranges
263
+	shrl	$10, %ecx		/* %cx = updated length in KB */
264
+	pushw	%cx			/* Will be picked up in %eax */
265
+	
266
+	popl	%eax
267
+	popl	%ecx
268
+	popw	%di
269
+	ret
270
+
271
+/****************************************************************************
272
+ * Intercept INT 15,88 calls and remove the hidden memory ranges
273
+ * from the resulting memory map.
274
+ ****************************************************************************
275
+ */
276
+intercept_88:
277
+	pushw	%bx			/* E801 adjust, ignore %bx */
278
+	call	e801_adjust
279
+	popw	%bx
280
+	jmp	intercept_int15_exit
281
+
282
+	.globl	e820mangler_end
283
+e820mangler_end:
284
+
285
+	.globl	_e820mangler_size
286
+	.equ	_e820mangler_size, e820mangler_end - e820mangler
287
+	.globl	e820mangler_size
288
+e820mangler_size:
289
+	.word	_e820mangler_size
290
+
291
+#else
292
+
293
+	.globl	_e820mangler_size
294
+	.equ	_e820mangler_size, 0
295
+	
296
+#endif /* CODE16 */

+ 94
- 0
src/arch/i386/firmware/pcbios/hidemem.c View File

@@ -0,0 +1,94 @@
1
+/* Utility functions to hide Etherboot by manipulating the E820 memory
2
+ * map.  These could go in memsizes.c, but are placed here because not
3
+ * all images will need them.
4
+ */
5
+
6
+#include "etherboot.h"
7
+#include "hidemem.h"
8
+
9
+#ifdef	CODE16
10
+
11
+static int mangling = 0;
12
+static void *mangler = NULL;
13
+
14
+#define INSTALLED(x)	( (typeof(&x)) ( (void*)(&x) - (void*)e820mangler \
15
+					 + mangler ) )
16
+#define intercept_int15		INSTALLED(_intercept_int15)
17
+#define intercepted_int15	INSTALLED(_intercepted_int15)
18
+#define hide_memory		INSTALLED(_hide_memory)
19
+#define INT15_VECTOR ( (segoff_t*) ( phys_to_virt( 4 * 0x15 ) ) )
20
+
21
+int install_e820mangler ( void *new_mangler ) {
22
+	if ( mangling ) return 0;
23
+	memcpy ( new_mangler, &e820mangler, e820mangler_size );
24
+	mangler = new_mangler;
25
+	return 1;
26
+}
27
+
28
+/* Intercept INT15 calls and pass them through the mangler.  The
29
+ * mangler must have been copied to base memory before making this
30
+ * call, and "mangler" must point to the base memory copy, which must
31
+ * be 16-byte aligned.
32
+ */
33
+int hide_etherboot ( void ) {
34
+	if ( mangling ) return 1;
35
+	if ( !mangler ) return 0;
36
+
37
+	/* Hook INT15 handler */
38
+	*intercepted_int15 = *INT15_VECTOR;
39
+	(*hide_memory)[0].start = virt_to_phys(_text);
40
+	(*hide_memory)[0].length = _end - _text;
41
+	/* IMPORTANT, possibly even FIXME:
42
+	 *
43
+	 * Etherboot has a tendency to claim a very large area of
44
+	 * memory as possible heap; enough to make it impossible to
45
+	 * load an OS if we hide all of it.  We hide only the portion
46
+	 * that's currently in use.  This means that we MUST NOT
47
+	 * perform further allocations from the heap while the mangler
48
+	 * is active.
49
+	 */
50
+	(*hide_memory)[1].start = heap_ptr;
51
+	(*hide_memory)[1].length = heap_bot - heap_ptr;
52
+	INT15_VECTOR->segment = SEGMENT(mangler);
53
+	INT15_VECTOR->offset = 0;
54
+
55
+	mangling = 1;
56
+	return 1;
57
+}
58
+
59
+int unhide_etherboot ( void ) {
60
+	if ( !mangling ) return 1;
61
+
62
+	/* Restore original INT15 handler
63
+	 */
64
+	if ( VIRTUAL(INT15_VECTOR->segment,INT15_VECTOR->offset) != mangler ) {
65
+		/* Oh dear... */
66
+
67
+#ifdef WORK_AROUND_BPBATCH_BUG
68
+		/* BpBatch intercepts INT15, so can't unhook it, and
69
+		 * then proceeds to ignore our PXENV_KEEP_UNDI return
70
+		 * status, which means that it ends up zeroing out the
71
+		 * INT15 handler routine.
72
+		 *
73
+		 * This rather ugly hack involves poking into
74
+		 * BpBatch's code and changing it's stored value for
75
+		 * the "next handler" in the INT15 chain.
76
+		 */
77
+		segoff_t *bp_chain = VIRTUAL ( 0x0060, 0x8254 );
78
+
79
+		if ( ( bp_chain->segment == SEGMENT(mangler) ) &&
80
+		     ( bp_chain->offset == 0 ) ) {
81
+			printf ( "\nBPBATCH bug workaround enabled\n" );
82
+			*bp_chain = *intercepted_int15;
83
+		}
84
+#endif /* WORK_AROUND_BPBATCH_BUG */
85
+
86
+		return 0;
87
+	}
88
+	*INT15_VECTOR = *intercepted_int15;
89
+
90
+	mangling = 0;
91
+	return 1;
92
+}
93
+
94
+#endif	/* CODE16 */

+ 201
- 0
src/arch/i386/firmware/pcbios/memsizes.c View File

@@ -0,0 +1,201 @@
1
+#ifdef PCBIOS
2
+
3
+#include "etherboot.h"
4
+#include "realmode.h"
5
+
6
+#define CF ( 1 << 0 )
7
+
8
+#ifndef MEMSIZES_DEBUG 
9
+#define MEMSIZES_DEBUG 0
10
+#endif
11
+
12
+/* by Eric Biederman */
13
+
14
+struct meminfo meminfo;
15
+
16
+/**************************************************************************
17
+BASEMEMSIZE - Get size of the conventional (base) memory
18
+**************************************************************************/
19
+unsigned short basememsize ( void )
20
+{
21
+	RM_FRAGMENT(rm_basememsize,
22
+		"int $0x12\n\t"
23
+	);	
24
+	return real_call ( rm_basememsize, NULL, NULL );
25
+}
26
+
27
+/**************************************************************************
28
+MEMSIZE - Determine size of extended memory
29
+**************************************************************************/
30
+unsigned int memsize ( void )
31
+{
32
+	struct {
33
+		reg16_t ax;
34
+	} PACKED in_stack;
35
+	struct {
36
+		reg16_t ax;
37
+		reg16_t bx;
38
+		reg16_t cx;
39
+		reg16_t dx;
40
+		reg16_t flags;
41
+	} PACKED out_stack;
42
+	int memsize;
43
+
44
+	RM_FRAGMENT(rm_memsize,
45
+	/* Some buggy BIOSes don't clear/set carry on pass/error of
46
+	 * e801h memory size call or merely pass cx,dx through without
47
+	 * changing them, so we set carry and zero cx,dx before call.
48
+	 */
49
+		"stc\n\t"
50
+		"xorw %cx,%cx\n\t"
51
+		"xorw %dx,%dx\n\t"
52
+		"popw %ax\n\t"
53
+		"int $0x15\n\t"
54
+		"pushfw\n\t"
55
+		"pushw %dx\n\t"
56
+		"pushw %cx\n\t"
57
+		"pushw %bx\n\t"
58
+		"pushw %ax\n\t"
59
+	);
60
+
61
+	/* Try INT 15,e801 first */
62
+	in_stack.ax.word = 0xe801;
63
+	real_call ( rm_memsize, &in_stack, &out_stack );
64
+	if ( out_stack.flags.word & CF ) {
65
+		/* INT 15,e801 not supported: try INT 15,88 */
66
+		in_stack.ax.word = 0x8800;
67
+		memsize = real_call ( rm_memsize, &in_stack, &out_stack );
68
+	} else {
69
+		/* Some BIOSes report extended memory via ax,bx rather
70
+		 * than cx,dx
71
+		 */
72
+		if ( (out_stack.cx.word==0) && (out_stack.dx.word==0) ) {
73
+			/* Use ax,bx */
74
+			memsize = ( out_stack.bx.word<<6 ) + out_stack.ax.word;
75
+		} else {
76
+			/* Use cx,dx */
77
+			memsize = ( out_stack.dx.word<<6 ) + out_stack.cx.word;
78
+		}
79
+	}
80
+	return memsize;
81
+}
82
+
83
+#define SMAP ( 0x534d4150 )
84
+int meme820 ( struct e820entry *buf, int count )
85
+{
86
+	struct {
87
+		reg16_t flags;
88
+		reg32_t eax;
89
+		reg32_t ebx;
90
+		struct e820entry entry;
91
+	} PACKED stack;
92
+	int index = 0;
93
+
94
+	RM_FRAGMENT(rm_meme820,
95
+		"addw $6, %sp\n\t"	/* skip flags, eax */
96
+		"popl %ebx\n\t"
97
+		"pushw %ss\n\t"	/* es:di = ss:sp */
98
+		"popw %es\n\t"
99
+		"movw %sp, %di\n\t"
100
+		"movl $0xe820, %eax\n\t"
101
+		"movl $" RM_STR(SMAP) ", %edx\n\t"
102
+		"movl $" RM_STR(E820ENTRY_SIZE) ", %ecx\n\t"
103
+		"int $0x15\n\t"
104
+		"pushl %ebx\n\t"
105
+		"pushl %eax\n\t"
106
+		"pushfw\n\t"
107
+	);
108
+
109
+	stack.ebx.dword = 0; /* 'EOF' marker */
110
+	while ( ( index < count ) &&
111
+		( ( index == 0 ) || ( stack.ebx.dword != 0 ) ) ) {
112
+		real_call ( rm_meme820, &stack, &stack );
113
+		if ( stack.eax.dword != SMAP ) return 0;
114
+		if ( stack.flags.word & CF ) return 0;
115
+		buf[index++] = stack.entry;
116
+	}
117
+	return index;
118
+}
119
+
120
+void get_memsizes(void)
121
+{
122
+	/* Ensure we don't stomp bios data structutres.
123
+	 * the interrupt table: 0x000 - 0x3ff
124
+	 * the bios data area:  0x400 - 0x502
125
+	 * Dos variables:       0x502 - 0x5ff
126
+	 */
127
+	static const unsigned min_addr = 0x600;
128
+	unsigned i;
129
+	unsigned basemem;
130
+	basemem = get_free_base_memory();
131
+	meminfo.basememsize = basememsize();
132
+	meminfo.memsize = memsize();
133
+#ifndef IGNORE_E820_MAP
134
+	meminfo.map_count = meme820(meminfo.map, E820MAX);
135
+#else
136
+	meminfo.map_count = 0;
137
+#endif
138
+	if (meminfo.map_count == 0) {
139
+		/* If we don't have an e820 memory map fake it */
140
+		meminfo.map_count = 2;
141
+		meminfo.map[0].addr = 0;
142
+		meminfo.map[0].size = meminfo.basememsize << 10;
143
+		meminfo.map[0].type = E820_RAM;
144
+		meminfo.map[1].addr = 1024*1024;
145
+		meminfo.map[1].size = meminfo.memsize << 10;
146
+		meminfo.map[1].type = E820_RAM;
147
+	}
148
+	/* Scrub the e820 map */
149
+	for(i = 0; i < meminfo.map_count; i++) {
150
+		if (meminfo.map[i].type != E820_RAM) {
151
+			continue;
152
+		}
153
+		/* Reserve the bios data structures */
154
+		if (meminfo.map[i].addr < min_addr) {
155
+			unsigned long delta;
156
+			delta = min_addr - meminfo.map[i].addr;
157
+			if (delta > meminfo.map[i].size) {
158
+				delta = meminfo.map[i].size;
159
+			}
160
+			meminfo.map[i].addr = min_addr;
161
+			meminfo.map[i].size -= delta;
162
+		}
163
+		/* Ensure the returned e820 map is in sync 
164
+		 * with the actual memory state 
165
+		 */
166
+		if ((meminfo.map[i].addr < 0xa0000) && 
167
+			((meminfo.map[i].addr + meminfo.map[i].size) > basemem))
168
+		{
169
+			if (meminfo.map[i].addr <= basemem) {
170
+				meminfo.map[i].size = basemem - meminfo.map[i].addr;
171
+			} else {
172
+				meminfo.map[i].addr = basemem;
173
+				meminfo.map[i].size = 0;
174
+			}
175
+		}
176
+	}
177
+#if MEMSIZES_DEBUG
178
+{
179
+	int i;
180
+	printf("basememsize %d\n", meminfo.basememsize);
181
+	printf("memsize %d\n",     meminfo.memsize);
182
+	printf("Memory regions(%d):\n", meminfo.map_count);
183
+	for(i = 0; i < meminfo.map_count; i++) {
184
+		unsigned long long r_start, r_end;
185
+		r_start = meminfo.map[i].addr;
186
+		r_end = r_start + meminfo.map[i].size;
187
+		printf("[%X%X, %X%X) type %d\n", 
188
+			(unsigned long)(r_start >> 32),
189
+			(unsigned long)r_start,
190
+			(unsigned long)(r_end >> 32),
191
+			(unsigned long)r_end,
192
+			meminfo.map[i].type);
193
+#if defined(CONSOLE_FIRMWARE)
194
+		sleep(1); /* No way to see 32 entries on a standard 80x25 screen... */
195
+#endif
196
+	}
197
+}
198
+#endif
199
+}
200
+
201
+#endif /* PCBIOS */

+ 45
- 0
src/arch/i386/include/bits/byteswap.h View File

@@ -0,0 +1,45 @@
1
+#ifndef ETHERBOOT_BITS_BYTESWAP_H
2
+#define ETHERBOOT_BITS_BYTESWAP_H
3
+
4
+static inline uint16_t __i386_bswap_16(uint16_t x)
5
+{
6
+	__asm__("xchgb %b0,%h0\n\t"
7
+		: "=q" (x)
8
+		: "0" (x));
9
+	return x;
10
+}
11
+
12
+static inline uint32_t __i386_bswap_32(uint32_t x)
13
+{
14
+	__asm__("xchgb %b0,%h0\n\t"
15
+		"rorl $16,%0\n\t"
16
+		"xchgb %b0,%h0"
17
+		: "=q" (x)
18
+		: "0" (x));
19
+	return x;
20
+}
21
+
22
+
23
+#define __bswap_constant_16(x) \
24
+	((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
25
+		(((uint16_t)(x) & 0xff00) >> 8)))
26
+
27
+#define __bswap_constant_32(x) \
28
+	((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
29
+		(((uint32_t)(x) & 0x0000ff00U) <<  8) | \
30
+		(((uint32_t)(x) & 0x00ff0000U) >>  8) | \
31
+		(((uint32_t)(x) & 0xff000000U) >> 24)))
32
+
33
+#define __bswap_16(x) \
34
+	((uint16_t)(__builtin_constant_p(x) ? \
35
+	__bswap_constant_16(x) : \
36
+	__i386_bswap_16(x)))
37
+
38
+
39
+#define __bswap_32(x) \
40
+	((uint32_t)(__builtin_constant_p(x) ? \
41
+	__bswap_constant_32(x) : \
42
+	__i386_bswap_32(x)))
43
+
44
+
45
+#endif /* ETHERBOOT_BITS_BYTESWAP_H */

+ 0
- 0
src/arch/i386/include/bits/cpu.h View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save