proc binary_name_ld_lib_so { } { return "ld-okl4.lib.so" }
proc binary_name_core_a    { } { return "core-okl4.a"    }
proc binary_name_timer     { } { return "pit_timer"      }

proc kernel_files { } { return okl4 }

proc boot_output { } { return "serial" }

##
# Get the base-okl4 repository
#
proc base_okl4_dir {} { return [repository_contains mk/spec-okl4.mk] }


##
# Read the location of the OKL4 directory from 'etc/okl4.conf'
#
proc okl4_dir { } {
	global _okl4_dir

	if {![info exists _okl4_dir]} {
		if {[file exists etc/okl4.conf]} {
			set _okl4_dir [exec sed -n "/^OKL4_DIR/s/^.*=\\s*//p" etc/okl4.conf]
			if {[file exists $_okl4_dir]} { return $_okl4_dir }
		}

		set _okl4_dir [base_okl4_dir]/contrib/okl4
	}

	return $_okl4_dir
}


set weaver_xml_template {
	<machine>
		<word_size size="0x20" />
		<virtual_memory name="virtual">
			<region base="0x120000" size="0x3fe00000" />
		</virtual_memory>
		<physical_memory name="system_dram">
			<region base="0x0" size="0xa000" type="dedicated" />
		</physical_memory>
		<physical_memory name="bios">
			<region base="0xf0000" size="0x10000" type="dedicated" />
		</physical_memory>
		<physical_memory name="rom_expansion">
			<region base="0x100000" size="0x1800000" type="dedicated" />
		</physical_memory>
		<physical_memory name="physical">
			<region base="0x2000000" size="0x30000000" type="conventional" />
		</physical_memory>
		<phys_device name="timer_dev">
			<interrupt name="int_timer0" number="0" />
		</phys_device>
		<phys_device name="serial_dev">
			<interrupt name="int_serial0" number="4" />
		</phys_device>
		<phys_device name="rtc_dev">
		</phys_device>
		<page_size size="0x1000" />
		<page_size size="0x400000" />
	</machine>
	<physical_pool name="system_dram" direct="true">
		<memory src="system_dram" />
	</physical_pool>

	<virtual_pool name="virtual">
		<memory src="virtual" />
	</virtual_pool>

	<physical_pool name="bios" direct="true">
		<memory src="bios" />
	</physical_pool>

	<physical_pool name="rom_expansion" direct="true">
		<memory src="rom_expansion" />
	</physical_pool>

	<physical_pool name="physical" direct="true">
		<memory src="physical" />
	</physical_pool>

	<kernel file="okl4_kernel" xip="false" >
		<dynamic max_threads="0x400" />
		<config>
			<option key="root_caps" value="4096"/>
		</config>
	</kernel>

	<rootprogram file="core" virtpool="virtual" physpool="physical" direct="true" />
}


proc run_boot_string { } {
	return "\n\r\033\\\[1m\033\\\[33mOKL4 -"
}


proc core_link_address { } { return "0x03000000" }


proc elfweaver {} {
	if { ![file exists tool/okl4/elfweaver] } { build lib/tools }
	return tool/okl4/elfweaver
}


##
# Populate directory with binaries on OKL4
#
proc run_boot_dir {binaries} {

	global weaver_xml_template

	#
	# Build kernel and dynamic linker if needed
	#
	set kernel_arg ""

	if {![file exists [run_dir]/genode/okl4]} { set kernel_arg kernel/okl4 }

	set targets "$kernel_arg"

	if {[llength $targets]} { build $targets }

	if {$kernel_arg != ""} { copy_file bin/okl4 [run_dir]/genode/okl4 }

	build_core_image $binaries
	exec mv [run_dir]/image.elf [run_dir].image

	#
	# Generate ELF weaver config
	#
	set fh [open "[run_dir].weaver.xml" "WRONLY CREAT TRUNC"]
	puts $fh {<?xml version="1.0"?>}
	puts $fh {<!DOCTYPE image SYSTEM "weaver-1.1.dtd">}
	puts $fh {<image>}
	regsub okl4_kernel $weaver_xml_template "[run_dir]/genode/okl4" weaver_xml_template
	regsub \"core\" $weaver_xml_template "\"[run_dir].image\"" weaver_xml_template
	puts $fh $weaver_xml_template
	puts $fh {</image>}
	close $fh

	#
	# Run ELF Weaver to create a boot image
	#
	set ret [exec [elfweaver] merge --output "[run_dir]/image.elf" "[run_dir].weaver.xml"]
	if {[regexp "error" $ret dummy]} {
		puts stderr "Elfweaver failed: $ret"
		exit -6
	}
	exec [cross_dev_prefix]strip [run_dir]/image.elf

	#
	# Keep only the ELF boot image, but remove stripped binaries
	#
	remove_genode_dir

	exec mkdir -p [run_dir]/boot
	exec mv [run_dir]/image.elf [run_dir]/boot/image.elf

	if {[have_include "image/iso"] || [have_include "image/disk"]} {

		if {[have_include "image/disk"]} {
			install_disk_bootloader_to_run_dir
		}

		if {[have_include "image/iso"]} {
			install_iso_bootloader_to_run_dir
		}

		#
		# Generate GRUB2 config file
		#
		set fh [create_header_grub2_config]

		# The core binary is part of the 'binaries' list but it must
		# appear right after 'sigma0' as boot module. Hence the special case.
		#
		puts $fh "menuentry 'Genode on OKL4' {"
		puts $fh " insmod multiboot"
		puts $fh " multiboot /boot/bender [boot_output]"
		puts $fh " module /boot/image.elf"
		puts $fh "}"
		close $fh
	}

	#
	# Build image
	#
	run_image

	if {[have_include "load/tftp"]} {
		#
		# Install PXE bootloader pulsar
		#
		install_pxe_bootloader_to_run_dir

		#
		# Generate pulsar config file
		#
		set fh [open "[run_dir]/config-52-54-00-12-34-56" "WRONLY CREAT TRUNC"]
		# load okl4 at 256M to avoid overwritting binary, adjust by need
		puts $fh " addr 0x10000000"
		puts $fh " exec /boot/bender [boot_output]"
		puts $fh " load /boot/image.elf"
		close $fh

		generate_tftp_config
	}
}


##
# Base source archive within depot
#
proc base_src { } {

	if {[have_spec x86_32]} { return base-okl4 }

	global specs

	puts stderr "Test requires base-okl4 kernel archive, which is missing for this build configuration"
	puts stderr "  SPECS=\"$specs\""
	exit 0
}
