1SubDir HAIKU_TOP src system boot ;
2
3UsePrivateHeaders [ FDirName libroot locale ] ;
4
5rule BuildOpenFirmwareLoader {
6	local haikuLoader = $(1) ;
7	local bootLoader = $(2) ;
8
9	Depends $(haikuLoader) : $(bootLoader) ;
10	MakeLocateDebug $(haikuLoader) ;
11
12	switch $(TARGET_ARCH) {
13		case ppc :
14			BuildCoffLoader $(haikuLoader) : $(bootLoader) ;
15		case sparc :
16			BuildAoutLoader $(haikuLoader) : $(bootLoader) ;
17		case * :
18			Exit "Currently unsupported arch:" $(TARGET_ARCH) ;
19	}
20}
21
22
23#
24# A.out haiku_loader creation
25#
26rule BuildAoutLoader {
27	local haikuLoader = $(1) ;
28	local bootLoader = $(2) ;
29
30	Depends $(haikuLoader) : $(bootLoader) ;
31	MakeLocateDebug $(haikuLoader) ;
32
33	ELF2AOUT on $(haikuLoader) = <build>elf2aout ;
34	Depends $(haikuLoader) : <build>elf2aout ;
35}
36
37actions BuildAoutLoader bind ELF2AOUT {
38	$(RM) -f $(1)
39	$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) \
40	$(ELF2AOUT) -o $(1) $(2)
41}
42
43
44#
45# Coff haiku_loader creation
46#
47rule BuildCoffLoader {
48	local coffLoader = $(1) ;
49	local bootLoader = $(2) ;
50	switch $(TARGET_ARCH) {
51		case ppc :
52			COFF_FORMAT on $(coffLoader) = xcoff-powermac ;
53		case * :
54			Exit "Currently unsupported coff arch:" $(TARGET_ARCH) ;
55	}
56	HACK_COFF on $(coffLoader) = <build>hack-coff ;
57
58	Depends $(coffLoader) : <build>hack-coff ;
59}
60
61actions BuildCoffLoader bind HACK_COFF {
62	$(RM) -f $(1)
63	# get the address of the COFF entry
64	$(TARGET_OBJCOPY_$(TARGET_KERNEL_ARCH)) -O symbolsrec $(2) $(2).syms
65	EP=`grep _coff_start $(2).syms | tr -d '\r' | cut -d'$' -f2`
66	$(RM) -f $(2).syms
67	# copy to XCOFF format and patch the entry point
68	$(TARGET_OBJCOPY_$(TARGET_KERNEL_ARCH)) -O $(COFF_FORMAT) --set-start="0x${EP}" $(2) $(1)
69	#$(CP) $(2) $(1)
70	# fill-in some fields objcopy missed
71	$(HACK_COFF) $(1)
72}
73
74
75#
76# BIOS haiku_loader creation
77#
78rule BuildBiosLoader {
79	local haikuLoader = $(1) ;
80	local bootLoader = $(2) ;
81
82	Depends $(haikuLoader) : $(bootLoader) ;
83	MakeLocateDebug $(haikuLoader) ;
84
85	on $(1) ResAttr $(1) : $(RESFILES) : false ;
86	if ! [ on $(1) return $(DONT_USE_BEOS_RULES) ] {
87		SetType $(1) ;
88		MimeSet $(1) ;
89	}
90}
91
92actions BuildBiosLoader {
93	$(RM) -f $(1)
94	$(TARGET_OBJCOPY_$(TARGET_KERNEL_ARCH)) -O binary $(2) $(1)
95}
96
97
98#
99# EFI loader creation
100#
101rule BuildEFILoader {
102	local efiLoader = $(1) ;
103	local bootLoader = $(2) ;
104
105	Depends $(efiLoader) : $(bootLoader) ;
106
107	switch $(TARGET_ARCH) {
108		case x86 :
109			OUTPUT_TARGET on $(efiLoader) = pei-i386 ;
110		case x86_64 :
111			OUTPUT_TARGET on $(efiLoader) = pei-x86-64 ;
112		case arm :
113			OUTPUT_TARGET on $(efiLoader) = binary ;
114		case arm64 :
115			OUTPUT_TARGET on $(efiLoader) = binary ;
116		case riscv64 :
117			OUTPUT_TARGET on $(efiLoader) = binary ;
118		case * :
119			Exit "Currently unsupported arch:" $(TARGET_ARCH) ;
120	}
121
122	MakeLocateDebug $(efiLoader) ;
123}
124
125actions BuildEFILoader
126{
127	$(RM) -f $(1)
128	if [ "$(OUTPUT_TARGET)" = "binary" ]; then
129		# no bfd support, fake efi Pe header
130		$(TARGET_OBJCOPY_$(TARGET_KERNEL_ARCH)) -j .text -j .sdata -j .data \
131			-j .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .dynstr \
132			-j _haiku_revision \
133			--output-target=$(OUTPUT_TARGET) $(2) $(1)
134	else
135		# bfd supports pe + efi for arch
136		$(TARGET_OBJCOPY_$(TARGET_KERNEL_ARCH)) -j .text -j .sdata -j .data \
137			-j .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .dynstr \
138			-j _haiku_revision \
139			--output-target=$(OUTPUT_TARGET) \
140			--subsystem=efi-app $(2) $(1)
141	fi
142}
143
144#
145# Sign our EFI Bootloader if a key has been provided
146# SignEFILoader <output> : <input> : <public_cert_file> : <private_key_file> ;
147#
148rule SignEFILoader
149{
150	local signedEFILoader = $(1) ;
151	local unsignedEFILoader = $(2) ;
152	local publicCert = $(3) ;
153	local privateKey = $(4) ;
154
155	Depends $(signedEFILoader) : $(unsignedEFILoader) ;
156
157	DB_CERT_FILE on $(signedEFILoader) = $(publicCert) ;
158	DB_KEY_FILE on $(signedEFILoader) = $(privateKey) ;
159}
160
161actions SignEFILoader
162{
163	$(RM) -f $(1)
164	echo "Signing EFI bootloader..."
165	sbsign --key $(DB_KEY_FILE) --cert $(DB_CERT_FILE) --output $(1) $(2)
166}
167
168#
169# Verify our EFI bootloader has been properly signed
170# VerifyEFILoader <loader> : <cert>
171#
172actions VerifyEFILoader
173{
174	sbverify --cert $(2) $(1)
175}
176
177
178#
179# U-boot image creation
180#
181rule BuildUImage image : data : args
182{
183    Depends $(image) : $(data) ;
184    LocalClean clean : $(image) ;
185    MKIMAGE_ARGS on $(image) = $(args) ;
186    colon on $(image) = ":" ;
187    local files = $(data:G=) ;
188    BuildUImage1 $(image) : $(data) ;
189}
190
191actions BuildUImage1
192{
193    mkimage $(MKIMAGE_ARGS) -d $(>:J=$(colon)) $(<)
194}
195
196#
197# Given a txt, generate a binary u-boot script
198#
199rule BuildUImageScript script : source
200{
201	Depends $(script) : $(source) ;
202	LocalClean clean : $(script) ;
203	SCRIPTNAME on $(script) = $(script) ;
204	FAKEOS on $(script) = "linux" ;
205	ARCH on $(script) = $(TARGET_ARCH) ;
206
207	if $(TARGET_ARCH) = "riscv64" || $(TARGET_ARCH) = "riscv32" {
208		ARCH on $(script) = "riscv" ;
209	}
210
211	BuildUImageScript1 $(script) : $(source) ;
212}
213
214actions BuildUImageScript1
215{
216	$(RM) -f $(1)
217	mkimage -A $(ARCH) -O $(FAKEOS) -T script -C none -n $(SCRIPTNAME) \
218		-d $(2) $(1)
219}
220
221# the bootsector on haiku_loader.amiga_m68k must be checksummed
222rule ChecksumAmigaLoader
223{
224	local haikuLoader = $(1) ;
225	local checksummer = <build>fixup_amiga_boot_checksum ;
226
227	Depends $(haikuLoader) : $(checksummer) ;
228
229	TARGET_CHECKSUM on $(haikuLoader) = $(checksummer) ;
230}
231
232actions ChecksumAmigaLoader bind TARGET_CHECKSUM
233{
234	$(TARGET_CHECKSUM) $(1)
235}
236
237# the bootsector on haiku_loader.atari_m68k must be checksummed
238rule ChecksumAtariLoader
239{
240	local haikuLoader = $(1) ;
241	local checksummer = <build>fixup_tos_boot_checksum ;
242
243	Depends $(haikuLoader) : $(checksummer) ;
244
245	TARGET_CHECKSUM on $(haikuLoader) = $(checksummer) ;
246}
247
248actions ChecksumAtariLoader bind TARGET_CHECKSUM {
249	$(TARGET_CHECKSUM) $(1)
250}
251
252
253
254# atari_m68k: AUTO folder PRG target
255# based on KernelLd
256rule AtariBootPrgLd
257{
258	# AtariBootPrgLd <name> : <objs> : <linkerscript> : <args> ;
259
260	LINK on $(1) = $(TARGET_LD_$(TARGET_KERNEL_ARCH)) ;
261
262	LINKFLAGS on $(1) = $(4) ;
263	if $(3) { LINKFLAGS on $(1) += --script=$(3) ; }
264
265	# Remove any preset LINKLIBS
266	LINKLIBS on $(1) = ;
267
268	# TODO: Do we really want to invoke SetupKernel here? The objects should
269	# have been compiled with KernelObjects anyway, so we're doing that twice.
270	SetupKernel $(2) ;
271
272	# Show that we depend on the libraries we need
273	LocalClean clean : $(1) ;
274	LocalDepends all : $(1) ;
275	Depends $(1) : $(2) ;
276
277	MakeLocateDebug $(1) ;
278
279}
280
281actions AtariBootPrgLd
282{
283	$(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ;
284}
285
286
287local extraSources = ;
288if $(TARGET_CC_IS_LEGACY_GCC_$(TARGET_KERNEL_ARCH)) = 1 {
289	extraSources += atomic.S ;
290}
291
292for platform in [ MultiBootSubDirSetup ] {
293	on $(platform) {
294		if $(TARGET_ARCH) = x86_64 && $(TARGET_BOOT_PLATFORM) = efi {
295			SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot os arch
296								x86_64 ] ;
297		} else {
298			SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot os arch
299									$(TARGET_KERNEL_ARCH_DIR) ] ;
300		}
301
302		SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix string ] ;
303		SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix stdlib ] ;
304		SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix locale ] ;
305		SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) kernel lib ] ;
306
307		BootMergeObject boot_libroot_$(platform:G=).o :
308			abs.c
309			ctype_loc.cpp
310			ctype_l.cpp
311			ctype.cpp
312			LocaleData.cpp
313			qsort.c
314			kernel_vsprintf.cpp
315			memchr.c
316			memcmp.c
317			memmove.c
318			strdup.cpp
319			strndup.cpp
320			strlen.cpp
321			strnlen.cpp
322			strcmp.c
323			strcasecmp.c
324			strncmp.c
325			strcat.c
326			strcpy.c
327			strerror.c
328			strlcat.c
329			strlcpy.c
330			strchr.c
331			strrchr.c
332			strtol.c
333			strtoul.c
334			$(extraSources)
335		;
336
337		AddResources haiku_loader.$(TARGET_BOOT_PLATFORM) : boot_loader.rdef ;
338
339		local archGrist = [ FGrist src system boot arch $(TARGET_KERNEL_ARCH_DIR) $(platform:G=) ] ;
340		local archObject = boot_arch_$(TARGET_KERNEL_ARCH).o ;
341		local ldflags = $(HAIKU_BOOT_LDFLAGS) $(HAIKU_BOOT_$(platform:G=:U)_LDFLAGS) ;
342		ldflags ?= $(TARGET_BOOT_LDFLAGS) ;
343
344		# needed by tarfs, packagefs, and video_splash.cpp
345		local supportLibs = [ FGrist boot_zlib.a ] ;
346		if [ FIsBuildFeatureEnabled zstd ] {
347			supportLibs += boot_zstd.a ;
348		}
349
350		# efi loader needs to be shared.
351		if $(TARGET_BOOT_PLATFORM) = efi {
352			ldflags += -shared ;
353			ldflags += -Map=$(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET)/efi.map ;
354		}
355
356		if $(TARGET_BOOT_PLATFORM) = riscv {
357			ldflags += -z notext ;
358		}
359
360		BootLd boot_loader_$(platform:G=) :
361			boot_platform_$(platform:G=).o
362			$(archObject:G=$(archGrist))
363			[ MultiBootGristFiles
364				boot_loader.a
365				boot_net.a
366				boot_partitions.a
367
368				# file systems
369				boot_bfs.a
370				boot_amiga_ffs.a
371				boot_tarfs.a
372				boot_fatfs.a
373				boot_packagefs.a
374
375				boot_loader.a
376					# a second time, so undefined references in the file systems can be
377					# resolved
378				$(supportLibs)
379			]
380
381			# libroot functions needed by the stage2 boot loader
382			boot_libroot_$(platform:G=).o
383
384			: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/boot_loader_$(platform:G=).ld
385			: $(ldflags)
386		;
387
388		MakeLocate <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) : [ FDirName $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) revisioned ] ;
389		CopySetHaikuRevision <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) : boot_loader_$(TARGET_BOOT_PLATFORM) ;
390
391		switch $(TARGET_BOOT_PLATFORM) {
392			case efi :
393				if $(HAIKU_BOOT_$(platform:G=:U)_PRIVATE_KEYFILE) {
394					BuildEFILoader haiku_loader.$(TARGET_BOOT_PLATFORM).unsigned
395						: <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
396					SignEFILoader haiku_loader.$(TARGET_BOOT_PLATFORM)
397						: haiku_loader.$(TARGET_BOOT_PLATFORM).unsigned
398						: [ FDirName $(HAIKU_TOP) data boot efi keys DB.crt ]
399						: $(HAIKU_BOOT_$(platform:G=:U)_PRIVATE_KEYFILE) ;
400					VerifyEFILoader haiku_loader.$(TARGET_BOOT_PLATFORM)
401						: [ FDirName $(HAIKU_TOP) data boot efi keys DB.crt ] ;
402				} else {
403					BuildEFILoader haiku_loader.$(TARGET_BOOT_PLATFORM)
404						: <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
405				}
406
407				if $(TARGET_ARCH) = arm || $(TARGET_ARCH) = riscv64 {
408					# These EFI platforms need u-boot to get them going
409					BuildUImageScript boot.scr
410						: [ FDirName $(HAIKU_TOP) data boot u-boot boot-$(TARGET_ARCH).scr.txt ] ;
411				}
412
413			case bios_ia32 :
414				BuildBiosLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
415
416			case pxe_ia32 :
417				BuildBiosLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
418
419			case openfirmware :
420				BuildOpenFirmwareLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
421
422			case u-boot :
423				local loader_entry = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOOT_LOADER_BASE)|bc` ;
424				BuildUImage haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM)
425					:
426					-A $(TARGET_ARCH) -O linux -T kernel -C none
427					-a $(HAIKU_BOOT_LOADER_BASE) -e $(loader_entry)
428					-n 'Haiku $(TARGET_KERNEL_ARCH) loader' ;
429				BuildUImage haiku-floppyboot.tgz.$(TARGET_BOOT_PLATFORM) : haiku-floppyboot.tgz :
430					-A $(TARGET_ARCH) -O linux -T ramdisk -C none
431					-n 'Haiku $(TARGET_KERNEL_ARCH) floppyboot' ;
432				BuildUImageScript boot.scr
433					: [ FDirName $(HAIKU_TOP) data boot u-boot boot-$(TARGET_ARCH).scr.txt ] ;
434
435			case amiga_m68k :
436				BuildBiosLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
437				ChecksumAmigaLoader haiku_loader.$(TARGET_BOOT_PLATFORM) ;
438
439			case atari_m68k :
440				BuildBiosLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
441				ChecksumAtariLoader haiku_loader.$(TARGET_BOOT_PLATFORM) ;
442
443				AtariBootPrgLd haiku.prg :
444					<revisioned>boot_loader_$(TARGET_BOOT_PLATFORM)
445					: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/boot_prg_$(TARGET_BOOT_PLATFORM).ld
446					: -Bstatic
447				;
448
449			case riscv :
450				BuildBiosLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
451
452			case next_m68k :
453				BuildAoutLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : <revisioned>boot_loader_$(TARGET_BOOT_PLATFORM) ;
454
455			case * :
456				Exit "Currently unsupported haiku_loader:" $(TARGET_BOOT_PLATFORM) ;
457		}
458	}
459}
460
461SubInclude HAIKU_TOP src system boot arch $(TARGET_KERNEL_ARCH_DIR) ;
462SubInclude HAIKU_TOP src system boot libs ;
463SubInclude HAIKU_TOP src system boot loader ;
464SubInclude HAIKU_TOP src system boot platform ;
465