Squash commits for public release

This commit is contained in:
2025-02-12 09:54:05 -05:00
commit 7118adc514
1108 changed files with 80873 additions and 0 deletions

13
build/boot/BUILD.gn Normal file
View File

@@ -0,0 +1,13 @@
group("boot") {
if (target_arch == "x86") {
deps = [ "x86:bootx86" ]
} else if (target_arch == "x86_64") {
deps = [ "x86_64:bootx86_64" ]
} else if (target_arch == "arm32") {
deps = [ "arm32:bootarm" ]
} else if (target_arch == "arm64") {
deps = [ "arm64:bootarm64" ]
} else if (target_arch == "riscv64") {
deps = [ "riscv64:bootriscv64" ]
}
}

111
build/boot/arm32/BUILD.gn Normal file
View File

@@ -0,0 +1,111 @@
boot_c_flags = [
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
]
boot_asm_flags = []
boot_ld_flags = []
if (kernel_symbols) {
boot_c_flags += [ "-ggdb" ]
}
boot_c_flags += [
"-fno-builtin",
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=soft",
"-fno-pie",
]
boot_asm_flags += [
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=softfp",
"-mcpu=cortex-a15",
]
boot_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
boot_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
boot_ld_flags += [
"--oformat",
"elf32-littlearm",
"/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.builtins-arm.a",
]
}
config("boot_flags") {
cflags = boot_c_flags
asmflags = boot_asm_flags
ldflags = boot_ld_flags
defines = [ "xOS_kernel" ]
}
linker_script =
rebase_path("//build/boot/$target_arch/boot_link.ld", root_build_dir)
# Use a strange __EMPTY_PATH_, empty string can't be passed as an arg.
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
devtree_compile_script_args = [
rebase_path("//firmware/$target_arch/$target_board.odt", root_build_dir),
rebase_path("$root_out_dir/firmware/$target_board.obt", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("devtree_compile") {
script = "//build/kernel/devtree_compile.py"
inputs = [ "//firmware/$target_arch/$target_board.odt" ]
outputs = [
"$root_out_dir/firmware/$target_board.obt",
"$root_out_dir/firmware/$target_board.obto",
]
args = devtree_compile_script_args
}
executable("bootarm") {
deps = [ ":devtree_compile" ]
output_name = "bootarm.bin"
sources = [
"//boot/arm32/drivers/pl181.c",
"//boot/arm32/drivers/uart.c",
"//boot/arm32/entry.s",
"//boot/arm32/hw/ram.c",
"//boot/arm32/main.c",
"//boot/arm32/start_kernel.s",
"//boot/arm32/vmm/vmm.c",
"//boot/libboot/crypto/sha256.c",
"//boot/libboot/crypto/signature.c",
"//boot/libboot/crypto/uint2048.c",
"//boot/libboot/crypto/validate.c",
"//boot/libboot/devtree/devtree.c",
"//boot/libboot/elf/elf_lite.c",
"//boot/libboot/fs/ext2_lite.c",
"//boot/libboot/log/log.c",
"//boot/libboot/mem/alloc.c",
"//boot/libboot/mem/mem.c",
]
include_dirs = [ "//boot" ]
configs = [ ":boot_flags" ]
ldflags = [
rebase_path("$root_out_dir/firmware/$target_board.obto", root_build_dir),
"-T$linker_script",
]
}

View File

@@ -0,0 +1,55 @@
_pa_base = 0x80010000;
ENTRY(_pa_base)
SECTIONS
{
. = _pa_base;
bootloader_start = .;
.text ALIGN(4K) :
{
*(.xos_boot_text)
*(.text)
*(.text.*)
}
.rodata ALIGN(4K) :
{
*(.rodata)
*(.rodata.*)
}
.rodata.odt ALIGN(4K) :
{
_odt_phys = .;
*(.odt)
_odt_phys_end = .;
}
.data ALIGN(4K) :
{
*(.data)
*(.data.*)
}
.bss ALIGN(4K) :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
.stack ALIGN(4K) :
{
STACK_SECONDARY_PHYZ_BASE = .;
. += 0x1000;
STACK_SECONDARY_PHYZ_TOP = .;
STACK_PHYZ_BASE = .;
. += 0x1000;
STACK_PHYZ_TOP = .;
}
.ARM.exidx : { *(.ARM.exidx) }
}

31
build/boot/arm64/BUILD.gn Normal file
View File

@@ -0,0 +1,31 @@
# Use a strange __EMPTY_PATH_, empty string can't be passed as an arg.
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
devtree_compile_script_args = [
rebase_path("//firmware/$target_arch/$target_board.odt", root_build_dir),
rebase_path("$root_out_dir/firmware/$target_board.obt", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("devtree_compile") {
script = "//build/kernel/devtree_compile.py"
inputs = [ "//firmware/$target_arch/$target_board.odt" ]
outputs = [
"$root_out_dir/firmware/$target_board.obt",
"$root_out_dir/firmware/$target_board.obto",
]
args = devtree_compile_script_args
}
group("bootarm64") {
deps = [
":devtree_compile",
"rawImage:rawImage",
]
}

View File

@@ -0,0 +1,63 @@
prekernel_c_flags = [
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
"-fno-builtin",
"-mcpu=cortex-a53+nofp+nosimd+nocrypto+nocrc",
"-fpie",
]
prekernel_asm_flags = [ "-mcpu=cortex-a53+nofp+nosimd+nocrypto+nocrc" ]
prekernel_ld_flags = [ "-nostdlib" ]
if (kernel_symbols) {
prekernel_c_flags += [ "-ggdb" ]
}
if (host == "gnu") {
prekernel_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
prekernel_ld_flags += [
"--oformat",
"binary",
]
}
config("prekernel_flags") {
cflags = prekernel_c_flags
asmflags = prekernel_asm_flags
ldflags = prekernel_ld_flags
defines = [ "xOS_prekernel" ]
}
linker_script =
rebase_path("//build/boot/$target_arch/prekernel/prekernel_link.ld",
root_build_dir)
executable("prekernelarm64") {
output_name = "prekernelarm64.bin"
sources = [
"//boot/arm64/prekernel/drivers/fb.c",
"//boot/arm64/prekernel/drivers/uart.c",
"//boot/arm64/prekernel/entry.S",
"//boot/arm64/prekernel/main.c",
"//boot/arm64/prekernel/vm.c",
"//boot/libboot/devtree/devtree.c",
"//boot/libboot/elf/elf_lite.c",
"//boot/libboot/log/log.c",
"//boot/libboot/mem/alloc.c",
"//boot/libboot/mem/mem.c",
]
include_dirs = [ "//boot" ]
configs = [ ":prekernel_flags" ]
ldflags = [ "-T$linker_script" ]
}

View File

@@ -0,0 +1,45 @@
/* PIC */
_pa_base = 0x0;
ENTRY(_pa_base)
SECTIONS
{
. = _pa_base;
PREKERNEL_START_OFFSET = .;
.text :
{
*(.xos_boot_text)
*(.text)
*(.text.*)
}
.rodata :
{
*(.rodata)
*(.rodata.*)
}
.data :
{
*(.data)
*(.data.*)
}
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
.stack ALIGN(4K) :
{
PREKERNEL_STACK_BASE_OFFSET = .;
. += 0x1000;
PREKERNEL_STACK_TOP_OFFSET = .;
}
PREKERNEL_END_OFFSET = .;
}

View File

@@ -0,0 +1,22 @@
if (target_arch == "arm64") {
action("rawImage") {
script = "make_raw_image.py"
sources = [
"$root_build_dir/base/boot/kernel.bin",
"$root_build_dir/prekernelarm64.bin",
]
outputs = [ "$root_build_dir/rawImage.bin" ]
args = [
rebase_path("$root_build_dir/prekernelarm64.bin", root_build_dir),
rebase_path("$root_build_dir/base/boot/kernel.bin", root_build_dir),
rebase_path("$root_out_dir/firmware/$target_board.obt", root_build_dir),
rebase_path("$root_build_dir/rawImage.bin", root_build_dir),
]
deps = [
"//build/boot/arm64:devtree_compile",
"//build/boot/arm64/prekernel:prekernelarm64",
"//build/kernel:kernel_build",
]
}
}

View File

@@ -0,0 +1,77 @@
import sys
import os
import subprocess
from construct import *
from elftools.elf.elffile import ELFFile
from elftools.elf.constants import SH_FLAGS
prekernel_path = sys.argv[1]
kernel_path = sys.argv[2]
devtree_path = sys.argv[3]
out_path = sys.argv[4]
build_dir_path = os.path.dirname(os.path.abspath(sys.argv[4]))
tmp_dir_path = build_dir_path + "/tmp"
rawimage_header_path = tmp_dir_path + "/rawimage_header.bin"
# GNU-LD can't convert ELF object format to Binary on the fly.
# Checking if output is an ELF and convertining it to binary.
prekernel_header = []
with open(prekernel_path, "rb") as f:
prekernel_header = f.read(4)
if prekernel_header == b'\x7fELF':
kernel_vaddr = 0
kernel_vaddr_end = 0
with open(prekernel_path, 'rb') as elffile:
signature_section = None
for section in ELFFile(elffile).iter_sections():
if (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) == SH_FLAGS.SHF_ALLOC:
kernel_vaddr_end = max(
kernel_vaddr_end, section['sh_addr'] + section['sh_size'])
output = subprocess.check_output(
"aarch64-elf-objcopy -O binary {0} {0}".format(prekernel_path), shell=True)
binary_blob_size = os.path.getsize(prekernel_path)
assert(binary_blob_size <= kernel_vaddr_end)
need_to_append = kernel_vaddr_end - binary_blob_size
with open(prekernel_path, 'r+b') as file:
_ = file.read()
padding = [0x0 for _ in range(need_to_append)]
file.write(bytearray(padding))
prekernel_size = os.path.getsize(prekernel_path)
rawimage_header_size = 8 * 8
kernel_size = os.path.getsize(kernel_path)
devtree_size = os.path.getsize(devtree_path)
ramdisk_size = 0
result = {
"kern_off": rawimage_header_size + prekernel_size,
"kern_size": kernel_size,
"devtree_off": rawimage_header_size + prekernel_size + kernel_size,
"devtree_size": devtree_size,
"ramdisk_off": 0,
"ramdisk_size": 0,
"rawimage_size": rawimage_header_size + prekernel_size + kernel_size + devtree_size + ramdisk_size,
"padding": 0,
}
rawimage_header = Struct(
"kern_off" / Int64ul,
"kern_size" / Int64ul,
"devtree_off" / Int64ul,
"devtree_size" / Int64ul,
"ramdisk_off" / Int64ul,
"ramdisk_size" / Int64ul,
"rawimage_size" / Int64ul,
"padding" / Int64ul,
).build(result)
with open(rawimage_header_path, "wb") as binfile:
binfile.write(bytes(rawimage_header))
output = subprocess.check_output("cat {0} {1} {2} {3} > {4}".format(
prekernel_path, rawimage_header_path, kernel_path, devtree_path, out_path), shell=True)

View File

@@ -0,0 +1,5 @@
group("bootriscv64") {
deps = [
"prekernel:prekernelriscv64",
]
}

View File

@@ -0,0 +1,125 @@
prekernel_c_flags = [
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
"-fno-builtin",
"-march=rv64ima",
"-mabi=lp64",
"-fpie",
"-mcmodel=medany",
]
prekernel_asm_flags = [
"-mcmodel=medany",
"-march=rv64ima",
"-mabi=lp64",
]
prekernel_ld_flags = [ "-nostdlib" ]
if (kernel_symbols) {
prekernel_c_flags += [ "-ggdb" ]
}
if (host == "gnu") {
prekernel_ld_flags += [
# "-mno-relax",
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
prekernel_ld_flags += [
"--oformat",
"elf64",
]
}
config("prekernel_flags") {
cflags = prekernel_c_flags
asmflags = prekernel_asm_flags
ldflags = prekernel_ld_flags
defines = [ "xOS_prekernel" ]
}
linker_script =
rebase_path("//build/boot/$target_arch/prekernel/prekernel_link.ld",
root_build_dir)
# Use a strange __EMPTY_PATH_, empty string can't be passed as an arg.
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
devtree_compile_script_args = [
rebase_path("//firmware/$target_arch/$target_board.odt", root_build_dir),
rebase_path("$root_out_dir/firmware/$target_board.obt", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("devtree_compile") {
script = "//build/kernel/devtree_compile.py"
inputs = [ "//firmware/$target_arch/$target_board.odt" ]
outputs = [
"$root_out_dir/firmware/$target_board.obt",
"$root_out_dir/firmware/$target_board.obto",
]
args = devtree_compile_script_args
}
embed_kernel_script_args = [
rebase_path("$root_build_dir/base/boot/kernel.bin", root_build_dir),
rebase_path("$root_build_dir/tmp/boot/kernel.o", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("embed_kernel") {
script = "embed_kernel.py"
sources = [ "$root_build_dir/base/boot/kernel.bin" ]
outputs = [ "$root_build_dir/tmp/boot/kernel.o" ]
args = embed_kernel_script_args
deps = [ "//build/kernel:kernel_build" ]
}
executable("prekernelriscv64") {
output_name = "prekernelriscv64.bin"
sources = [
"//boot/libboot/devtree/devtree.c",
"//boot/libboot/elf/elf_lite.c",
"//boot/libboot/log/log.c",
"//boot/libboot/mem/alloc.c",
"//boot/libboot/mem/mem.c",
"//boot/riscv64/prekernel/drivers/uart.c",
"//boot/riscv64/prekernel/entry.S",
"//boot/riscv64/prekernel/main.c",
"//boot/riscv64/prekernel/vm.c",
]
include_dirs = [ "//boot" ]
inputs = [
"$root_out_dir/firmware/$target_board.obto",
"$root_out_dir/tmp/boot/kernel.o",
]
deps = [
":devtree_compile",
":embed_kernel",
]
configs = [ ":prekernel_flags" ]
ldflags = [
# Embeding kernel elf file into rawimage.
rebase_path("$root_out_dir/firmware/$target_board.obto", ""),
rebase_path("$root_out_dir/tmp/boot/kernel.o", ""),
"-T$linker_script",
]
}

View File

@@ -0,0 +1,30 @@
import sys
import os
import subprocess
prekernel_path = sys.argv[1]
out_path = sys.argv[2]
arch = sys.argv[3]
board = sys.argv[4]
host = sys.argv[5]
path_to_bins = sys.argv[6]
if path_to_bins == "__EMPTY_PATH_":
path_to_bins = ""
if len(path_to_bins) != 0:
if path_to_bins[-1] != '/':
path_to_bins += "/"
if host == "gnu":
OBJCOPY_TOOL = "{0}riscv64-unknown-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleriscv"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleriscv"
else:
print("Unsupported host {0}".format(host))
exit(0)
cmd = "{0} -I binary -O {1} --rename-section .data=.kernelelf {2} {3}".format(
OBJCOPY_TOOL, OBJCOPY_TARGET, prekernel_path, out_path)
output = subprocess.check_output(cmd, shell=True)

View File

@@ -0,0 +1,72 @@
_pa_base = 0x80000000;
ENTRY(_pa_base)
SECTIONS
{
. = _pa_base;
PREKERNEL_START_OFFSET = .;
.text :
{
*(.xos_boot_text)
*(.text)
*(.text.*)
}
.rodata :
{
*(.rodata)
*(.rodata.*)
}
.data :
{
*(.data)
*(.data.*)
}
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
.rela.text :
{
*(.rela.text)
}
.rela.bss :
{
*(.rela.bss)
}
.stack ALIGN(4K) :
{
PREKERNEL_STACK_BASE_OFFSET = .;
. += 0x1000;
PREKERNEL_STACK_TOP_OFFSET = .;
}
PREKERNEL_END_OFFSET = .;
.devtree ALIGN(4K) :
{
EMBED_DEVTREE_START = .;
*(.odt)
EMBED_DEVTREE_END = .;
}
DEVTREE_END = .;
.kernelelf ALIGN(4K) :
{
EMBED_KERNEL_START = .;
*(.kernelelf)
EMBED_KERNEL_END = .;
}
RAWIMAGE_END = .;
}

20
build/boot/x86/BUILD.gn Normal file
View File

@@ -0,0 +1,20 @@
if (target_arch == "x86") {
action("bootx86") {
script = "make_boot_drive.py"
sources = [
"$root_build_dir/stage1.bin",
"$root_build_dir/stage2.bin",
]
outputs = [ "$root_build_dir/os-image.bin" ]
args = [
rebase_path("$root_build_dir/stage1.bin", root_build_dir),
rebase_path("$root_build_dir/stage2.bin", root_build_dir),
rebase_path("$root_build_dir/os-image.bin", root_build_dir),
]
deps = [
"stage1:stage1",
"stage2:stage2",
]
}
}

View File

@@ -0,0 +1,42 @@
_pa_base = 0x1000;
ENTRY(_pa_base)
SECTIONS
{
. = _pa_base;
bootloader_start = .;
.text ALIGN(4K) :
{
*(.xos_boot_text)
*(.text)
*(.text.*)
}
.rodata :
{
*(.rodata)
*(.rodata.*)
}
.data :
{
*(.data)
*(.data.*)
}
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
.stack ALIGN(4K) :
{
STACK_PHYZ_BASE = .;
. += 0x1000;
STACK_PHYZ_TOP = .;
}
}

View File

@@ -0,0 +1,7 @@
import sys
inf = sys.argv[1]
outf = sys.argv[2]
reli = sys.argv[3]
import subprocess
output = subprocess.check_output("cat {0} {1} > {2}".format(inf, outf, reli), shell=True)

View File

@@ -0,0 +1,21 @@
action("stage1") {
script = "compile_stage1.py"
sources = [ "//boot/x86/stage1/boot.s" ]
outputs = [ "$root_build_dir/stage1.bin" ]
inputs = [
"//boot/x86/stage1/boot.s",
"//boot/x86/stage1/utils16/disk_load.s",
"//boot/x86/stage1/utils16/print.s",
"//boot/x86/stage1/utils16/smm.s",
"//boot/x86/stage1/utils16/switch_to_pm.s",
"//boot/x86/stage1/utils32/gdt.s",
"//boot/x86/stage1/utils32/print.s",
]
args = [
rebase_path("//boot/x86/stage1/boot.s", root_build_dir),
rebase_path(root_build_dir, root_build_dir),
rebase_path("//", root_build_dir),
]
}

View File

@@ -0,0 +1,7 @@
import sys
inf = sys.argv[1]
outf = sys.argv[2]
reli = sys.argv[3]
import subprocess
output = subprocess.check_output("nasm {0} -f bin -i {2} -o {1}/stage1.bin".format(inf, outf, reli), shell=True)

View File

@@ -0,0 +1,48 @@
linker_script =
rebase_path("//build/boot/$target_arch/boot_link.ld", root_build_dir)
executable("stage2") {
output_name = "stage2.bin"
sources = [
"//boot/libboot/crypto/sha256.c",
"//boot/libboot/crypto/signature.c",
"//boot/libboot/crypto/uint2048.c",
"//boot/libboot/crypto/validate.c",
"//boot/libboot/devtree/devtree.c",
"//boot/libboot/elf/elf_lite.c",
"//boot/libboot/fs/ext2_lite.c",
"//boot/libboot/log/log.c",
"//boot/libboot/mem/alloc.c",
"//boot/libboot/mem/mem.c",
"//boot/x86/stage2/drivers/ata.c",
"//boot/x86/stage2/drivers/port.c",
"//boot/x86/stage2/drivers/uart.c",
"//boot/x86/stage2/mem/vm.c",
"//boot/x86/stage2/stage2.c",
"//boot/x86/stage2/stage2_entry.s",
]
include_dirs = [ "//boot" ]
ldflags = [
"-T$linker_script",
"--oformat",
"binary",
"-Map=stage2.map",
]
cflags = [
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
"-mno-80387",
"-mno-mmx",
"-mno-sse",
"-mno-sse2",
]
asmflags = [
"-f",
"elf",
]
}

View File

@@ -0,0 +1,5 @@
group("bootx86_64") {
deps = [
"rawImage:rawImage",
]
}

View File

@@ -0,0 +1,92 @@
prekernel_c_flags = [
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
"-fno-builtin",
"-mno-80387",
"-mno-mmx",
"-mno-sse",
"-mno-sse2",
"-fpie",
"-mno-red-zone",
"-fno-omit-frame-pointer",
]
prekernel_asm_flags = [
"-w+all",
"-Werror",
"-f",
"elf64",
]
prekernel_ld_flags = [ "-nostdlib" ]
if (kernel_symbols) {
prekernel_c_flags += [ "-ggdb" ]
}
if (host == "llvm") {
prekernel_ld_flags += [
"--oformat",
"elf64",
]
}
config("prekernel_flags") {
cflags = prekernel_c_flags
asmflags = prekernel_asm_flags
ldflags = prekernel_ld_flags
defines = [ "xOS_prekernel" ]
}
linker_script =
rebase_path("//build/boot/$target_arch/prekernel/prekernel_link.ld",
root_build_dir)
# Use a strange __EMPTY_PATH_, empty string can't be passed as an arg.
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
embed_kernel_script_args = [
rebase_path("$root_build_dir/base/boot/kernel.bin", root_build_dir),
rebase_path("$root_build_dir/tmp/boot/kernel.o", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("embed_kernel") {
script = "embed_kernel.py"
sources = [ "$root_build_dir/base/boot/kernel.bin" ]
outputs = [ "$root_build_dir/tmp/boot/kernel.o" ]
args = embed_kernel_script_args
deps = [ "//build/kernel:kernel_build" ]
}
executable("prekernelx86_64") {
output_name = "prekernelx86_64.bin"
inputs = [ "$root_build_dir/tmp/boot/kernel.o" ]
sources = [
"//boot/libboot/elf/elf_lite.c",
"//boot/libboot/log/log.c",
"//boot/libboot/mem/alloc.c",
"//boot/libboot/mem/mem.c",
"//boot/x86_64/prekernel/drivers/uart.c",
"//boot/x86_64/prekernel/main.c",
"//boot/x86_64/prekernel/mboot1.S",
"//boot/x86_64/prekernel/vm.c",
]
deps = [ ":embed_kernel" ]
include_dirs = [ "//boot" ]
configs = [ ":prekernel_flags" ]
ldflags = [
# Embeding kernel elf file into rawimage.
rebase_path("$root_out_dir/tmp/boot/kernel.o", ""),
"-T$linker_script",
]
}

View File

@@ -0,0 +1,30 @@
import sys
import os
import subprocess
prekernel_path = sys.argv[1]
out_path = sys.argv[2]
arch = sys.argv[3]
board = sys.argv[4]
host = sys.argv[5]
path_to_bins = sys.argv[6]
if path_to_bins == "__EMPTY_PATH_":
path_to_bins = ""
if len(path_to_bins) != 0:
if path_to_bins[-1] != '/':
path_to_bins += "/"
if host == "gnu":
OBJCOPY_TOOL = "{0}x86_64-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-x86-64"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-x86-64"
else:
print("Unsupported host {0}".format(host))
exit(0)
cmd = "{0} -I binary -O {1} --rename-section .data=.kernelelf {2} {3}".format(
OBJCOPY_TOOL, OBJCOPY_TARGET, prekernel_path, out_path)
output = subprocess.check_output(cmd, shell=True)

View File

@@ -0,0 +1,59 @@
/* PIC */
_pa_base = 1M;
/* ENTRY(_pa_base) */
SECTIONS
{
. = _pa_base;
PREKERNEL_START = .;
.multiboot :
{
*(.multiboot)
}
.text :
{
*(.xos_boot_text)
*(.text)
*(.text.*)
}
.rodata :
{
*(.rodata)
*(.rodata.*)
}
.data :
{
*(.data)
*(.data.*)
}
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
.stack ALIGN(4K) :
{
PREKERNEL_STACK_BASE = .;
. += 0x1000;
PREKERNEL_STACK_TOP = .;
}
PREKERNEL_END = .;
.kernelelf ALIGN(4K) :
{
EMBED_KERNEL_START = .;
*(.kernelelf)
EMBED_KERNEL_END = .;
}
RAWIMAGE_END = .;
}

View File

@@ -0,0 +1,23 @@
if (target_arch == "x86_64") {
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
make_raw_image_script_args = [
rebase_path("$root_build_dir/prekernelx86_64.bin", root_build_dir),
rebase_path("$root_build_dir/rawImage.elf", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("rawImage") {
script = "make_raw_image.py"
sources = [ "$root_build_dir/prekernelx86_64.bin" ]
outputs = [ "$root_build_dir/rawImage.elf" ]
args = make_raw_image_script_args
deps = [ "//build/boot/x86_64/prekernel:prekernelx86_64" ]
}
}

View File

@@ -0,0 +1,30 @@
import sys
import os
import subprocess
prekernel_path = sys.argv[1]
out_path = sys.argv[2]
arch = sys.argv[3]
board = sys.argv[4]
host = sys.argv[5]
path_to_bins = sys.argv[6]
if path_to_bins == "__EMPTY_PATH_":
path_to_bins = ""
if len(path_to_bins) != 0:
if path_to_bins[-1] != '/':
path_to_bins += "/"
if host == "gnu":
OBJCOPY_TOOL = "{0}x86_64-elf-objcopy".format(path_to_bins)
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
else:
print("Unsupported host {0}".format(host))
exit(0)
# rawImage for x86 is a multiboot-capable elf file. Since qemu does not
# implement support for multiboot2 specs, which could load elf64, we have
# to change the type of the elf file to elf32-i686.
output = subprocess.check_output(
"{0} -O elf32-i386 {1} {2}".format(OBJCOPY_TOOL, prekernel_path, out_path), shell=True)

View File

@@ -0,0 +1,70 @@
declare_args() {
# Common
debug_build = true
optimize = true
host = "gnu"
llvm_bin_path = ""
device_type = "desktop"
target_arch = ""
target_board = ""
# Kernel Flags
kernel_symbols = true
kernel_preempt = true
# Userland
userland_symbols = true
compile_tests = true
objc_support = false
test_method = "none"
}
if (target_arch == "") {
# target_cpu is deprecated, but not fully deleted.
if (target_cpu != "") {
target_arch = target_cpu
} else {
target_arch = "x86"
}
}
if (target_arch == "arm") {
target_arch = "arm32"
}
if (target_arch == "aarch64") {
target_arch = "arm64"
}
if (device_type == "m") {
device_type = "mobile"
}
if (device_type == "d") {
device_type = "desktop"
}
if (target_arch == "x86") {
target_board = "i386"
}
if (target_arch == "x86_64") {
target_board = "x86_64"
}
if (target_arch == "arm32") {
# Currently we support only vexpress-a15.
target_board = "vexpress-a15"
}
if (target_arch == "arm64") {
if (target_board == "") {
target_board = "qemu_virt"
}
}
if (target_arch == "riscv64") {
target_board = "riscv64"
}
if (host == "gnu") {
set_default_toolchain("//toolchains:gnu-cross-compiler")
}
if (host == "llvm") {
objc_support = true
llvm_bin_path = getenv("LLVM_BIN_PATH")
set_default_toolchain("//toolchains:llvm-cross-compiler")
}

257
build/kernel/BUILD.gn Normal file
View File

@@ -0,0 +1,257 @@
import("//build/security/SIGN_TEMPLATE.gni")
kernel_out_path = "base/boot"
kernel_c_flags = [
"-std=gnu11",
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
"-fpie",
]
kernel_asm_flags = []
kernel_ld_flags = []
if (debug_build) {
kernel_c_flags += [ "-DDEBUG_KERNEL" ]
}
if (kernel_symbols) {
kernel_c_flags += [ "-ggdb" ]
}
if (optimize) {
kernel_c_flags += [ "-Os" ]
if (host == "llvm") {
kernel_c_flags += [ "-flto" ]
if (target_arch == "x86_64") {
kernel_c_flags += [
"-mllvm",
"-code-model=large",
]
}
}
}
if (target_arch == "x86" && kernel_preempt) {
kernel_c_flags += [ "-DPREEMPT_KERNEL" ]
}
if (device_type == "desktop") {
kernel_c_flags += [ "-DTARGET_DESKTOP" ]
}
if (device_type == "mobile") {
kernel_c_flags += [ "-DTARGET_MOBILE" ]
}
if (target_arch == "x86") {
kernel_c_flags += [
"-mno-80387",
"-mno-mmx",
"-mno-sse",
"-mno-sse2",
]
kernel_asm_flags += [
"-w+all",
"-Werror",
"-f",
"elf",
]
kernel_ld_flags += [
"--oformat",
"elf32-i386",
]
}
if (target_arch == "x86_64") {
kernel_c_flags += [
"-mno-80387",
"-mno-mmx",
"-mno-sse",
"-mno-sse2",
"-mno-red-zone",
"-fno-omit-frame-pointer",
"-mcmodel=large",
]
kernel_asm_flags += [
"-w+all",
"-Werror",
"-f",
"elf64",
]
if (host == "llvm") {
kernel_ld_flags += [
"--oformat",
"elf64",
]
}
}
if (target_arch == "arm32") {
kernel_c_flags += [
"-fno-builtin",
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=soft",
]
kernel_asm_flags += [
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=softfp",
"-mcpu=cortex-a15",
]
kernel_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
kernel_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
kernel_ld_flags += [
"--oformat",
"elf32-littlearm",
rebase_path("//toolchains/llvm_runtime/11.1.0/libclang_rt.builtins-arm.a",
root_build_dir),
]
}
}
if (target_arch == "arm64") {
kernel_c_flags += [
"-fno-builtin",
"-mcpu=cortex-a53+nofp+nosimd+nocrypto+nocrc",
]
kernel_asm_flags += [ "-mcpu=cortex-a53+nofp+nosimd+nocrypto+nocrc" ]
kernel_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
kernel_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
kernel_ld_flags += [
"--oformat",
"elf64-littlearm",
]
}
# Qemu virt is used as a test platform.
if (target_board == "qemu_virt") {
kernel_c_flags += [ "-DTARGET_QEMU_VIRT" ]
kernel_asm_flags += [ "-DTARGET_QEMU_VIRT" ]
}
if (target_board == "apl") {
kernel_c_flags += [ "-DTARGET_APL" ]
kernel_asm_flags += [ "-DTARGET_APL" ]
}
# Enabling KASAN only for GCC builds as LLVM has fixed KASAN shadow bases
# which are incompatible with xOS layout.
if (debug_build && host == "gnu") {
kernel_c_flags += [
"-fsanitize=kernel-address",
"-DKASAN_ENABLED",
]
}
}
if (target_arch == "riscv64") {
kernel_c_flags += [
"-fno-builtin",
"-march=rv64ima",
"-mabi=lp64",
"-mcmodel=medany",
]
kernel_asm_flags += [
"-mcmodel=medany",
"-march=rv64ima",
"-mabi=lp64",
]
kernel_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
kernel_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
rebase_path("//toolchains/gcc_runtime/10.2.1/riscv64-libgcc.a",
root_build_dir),
]
}
if (host == "llvm") {
kernel_ld_flags += [
"--oformat",
"elf64",
rebase_path("//toolchains/gcc_runtime/10.2.1/riscv64-libgcc.a",
root_build_dir),
]
}
}
config("kernel_flags") {
cflags = kernel_c_flags
asmflags = kernel_asm_flags
ldflags = kernel_ld_flags
defines = [ "xOS_kernel" ]
}
kernel_src = exec_script("get_kernel_files.py",
[
rebase_path("//src", root_build_dir),
target_arch,
],
"list lines")
linker_script =
rebase_path("//build/kernel/$target_arch/kernel_link.ld", root_build_dir)
action("kernel_config") {
script = "//build/kernel/gen_config.py"
outputs = [ "$root_out_dir/base/boot/kernel.config" ]
args = [
rebase_path("$root_out_dir/base/boot/kernel.config", root_build_dir),
"$target_arch",
"$host",
]
}
executable("kernel_build") {
deps = [ ":kernel_config" ]
output_name = "$kernel_out_path/kernel.bin"
sources = kernel_src
include_dirs = [ "//kernel/include" ]
configs = [ ":kernel_flags" ]
ldflags = [
# See comment at EXEC_TEMPLATE.gni about elfsign_section.o.
# It is required to sign a binary.
rebase_path("$root_out_dir/tmp/elfsign_section.o", ""),
"-T$linker_script",
]
}
xOS_signexec("kernel") {
binpath = "boot/kernel.bin"
}
group("kernel") {
deps = [
":kernel_build",
":sign_kernel",
]
}

View File

@@ -0,0 +1,83 @@
_pa_base = 0x80100000;
_va_base = 0xc0000000;
ENTRY(_va_base)
SECTIONS
{
. = _va_base;
__text_start = .;
.text ALIGN(4K) : AT (ADDR(.text) - _va_base + _pa_base)
{
*(.interrupt_vector_table)
*(.text)
*(.text.*)
}
__text_end = .;
__rodata_start = .;
.rodata ALIGN(4K) : AT (ADDR(.rodata) - _va_base + _pa_base)
{
*(.rodata)
*(.rodata.*)
}
.rodata.driver_init ALIGN(4K) : AT (ADDR(.rodata.driver_init) - _va_base + _pa_base)
{
_drivers_init_start = .;
*(SORT_BY_NAME(.driver_init_sections.*))
_drivers_init_end = .;
}
__rodata_end = .;
__data_start = .;
.data ALIGN(4K) : AT (ADDR(.data) - _va_base + _pa_base)
{
*(.data)
*(.data.*)
}
__data_end = .;
__bss_start = .;
.bss ALIGN(4K) : AT (ADDR(.bss) - _va_base + _pa_base)
{
*(.bss)
*(.bss.*)
*(COMMON)
}
__bss_end = .;
__stack_start = .;
.stack ALIGN(4K) : AT (ADDR(.stack) - _va_base + _pa_base)
{
STACK_SECONDARY_BASE = .;
. += 0x1000;
STACK_SECONDARY_TOP = .;
STACK_BASE = .;
. += 0x1000;
STACK_TOP = .;
STACK_SVC_BASE = .;
. += 0x1000;
STACK_SVC_TOP = .;
STACK_IRQ_BASE = .;
. += 0x1000;
STACK_IRQ_TOP = .;
STACK_ABORT_BASE = .;
. += 0x1000;
STACK_ABORT_TOP = .;
STACK_UNDEFINED_BASE = .;
. += 0x1000;
STACK_UNDEFINED_TOP = .;
}
__stack_end = .;
.ARM.exidx : { *(.ARM.exidx) }
__end = .;
}

View File

@@ -0,0 +1,67 @@
_pa_base = 0x0;
_va_base = 0xffffff8000000000;
ENTRY(_va_base)
SECTIONS
{
. = _va_base;
__text_start = .;
.text ALIGN(4K) : AT (ADDR(.text) - _va_base + _pa_base)
{
*(.xos_kernel_boot)
*(.text)
*(.text.*)
}
__text_end = .;
__rodata_start = .;
.rodata ALIGN(4K) : AT (ADDR(.rodata) - _va_base + _pa_base)
{
*(.rodata)
*(.rodata.*)
}
.rodata.driver_init ALIGN(4K) : AT (ADDR(.rodata.driver_init) - _va_base + _pa_base)
{
_drivers_init_start = .;
*(SORT_BY_NAME(.driver_init_sections.*))
_drivers_init_end = .;
}
__rodata_end = .;
__data_start = .;
.data ALIGN(4K) : AT (ADDR(.data) - _va_base + _pa_base)
{
*(.data)
*(.data.*)
}
__data_end = .;
__bss_start = .;
.bss ALIGN(4K) : AT (ADDR(.bss) - _va_base + _pa_base)
{
*(.bss)
*(.bss.*)
*(COMMON)
}
__bss_end = .;
__stack_start = .;
.stack ALIGN(4K) : AT (ADDR(.stack) - _va_base + _pa_base)
{
STACK_SECONDARY_BASE = .;
. += 0x1000;
STACK_SECONDARY_TOP = .;
STACK_BASE = .;
. += 0x1000;
STACK_TOP = .;
}
__stack_end = .;
.ARM.exidx : { *(.ARM.exidx) }
__end = .;
}

View File

@@ -0,0 +1,61 @@
import os
import glob
import sys
import json
import subprocess
from datetime import datetime
OBJCOPY_TOOL = ""
OBJCOPY_TARGET = ""
def shell(cmd, cwd=None):
return subprocess.check_output(cmd, shell=True, cwd=cwd).decode("ascii")
inpath = sys.argv[1]
outpath = sys.argv[2]
arch = sys.argv[3]
board = sys.argv[4]
host = sys.argv[5]
path_to_bins = sys.argv[6]
if path_to_bins == "__EMPTY_PATH_":
path_to_bins = ""
if len(path_to_bins) != 0:
if path_to_bins[-1] != '/':
path_to_bins += "/"
if (arch == "arm32"):
if host == "gnu":
OBJCOPY_TOOL = "{0}arm-none-eabi-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf32-littlearm"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf32-littlearm"
elif (arch == "arm64"):
if host == "gnu":
OBJCOPY_TOOL = "{0}aarch64-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleaarch64"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleaarch64"
elif (arch == "riscv64"):
if host == "gnu":
OBJCOPY_TOOL = "{0}riscv64-unknown-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleriscv"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleriscv"
else:
print("Unsupported arch {0}".format(arch))
exit(1)
run_from = os.getcwd() + '/../utils/compilers/DevTreeCompiler'
inpath_abs = os.getcwd() + '/' + inpath
outpath_abs = os.getcwd() + '/' + outpath
obj_outpath_abs = outpath_abs + "o"
shell("python3 . {0} {1}".format(inpath_abs, outpath_abs), run_from)
shell("{0} -I binary -O {1} --rename-section .data=.odt {2} {3}".format(
OBJCOPY_TOOL, OBJCOPY_TARGET, outpath_abs, obj_outpath_abs))

View File

@@ -0,0 +1,42 @@
import os
import glob
import sys
import json
import subprocess
from datetime import datetime
def shell(cmd):
return subprocess.check_output(cmd, shell=True).decode("ascii")
outpath = sys.argv[1]
arch = sys.argv[2]
host = sys.argv[3]
branch = "{0}@{1}".format(shell("git rev-parse --short HEAD")[:-1], shell("git rev-parse --abbrev-ref HEAD")[:-1])
config = {}
config['arch'] = arch
config['host'] = host
config['branch'] = branch
config['time'] = datetime.today().strftime('%Y-%m-%d %H:%M:%S')
# Printing to the file
def print_header(config_file):
config_file.write(
"""#
# Automatically generated file; DO NOT EDIT.
# xOS Kernel Configuration
#
""")
def print_json(config_file, rdict):
json.dump(rdict, config_file, indent = 4)
config_file = open(outpath, "w")
print_header(config_file)
print_json(config_file, config)
config_file.close()

View File

@@ -0,0 +1,77 @@
import os
import glob
import sys
# sys.argv[2] Target to generate for
target = sys.argv[2]
platforms = ['x86', 'i386', 'x86_64', 'arm',
'arm32', 'arm64', 'aarch32', 'aarch64',
'riscv', 'riscv64']
bits = ['bits32', 'bits64']
platform_to_bits = {
"x86": "bits32",
"x86_64": "bits64",
"arm32": "bits32",
"arm64": "bits64",
"riscv64": "bits64",
}
allowed_paths = {
"x86": ["x86", "i386"],
"x86_64": ["x86", "x86_64"],
"arm32": ["aarch32", "arm32", "arm"],
"arm64": ["aarch64", "arm64", "arm"],
"riscv64": ["riscv64", "riscv"]
}
ignore_platforms = []
ignore_bits = []
allowed_paths_for_target = allowed_paths.get(target, None)
if allowed_paths_for_target is None:
print("Unknown platform {0}".format(target))
exit(1)
for platform in platforms:
if not (platform in allowed_paths_for_target):
ignore_platforms.append(platform)
for bit in bits:
if platform_to_bits[target] != bit:
ignore_bits.append(bit)
def is_file_type(name, ending):
if len(name) <= len(ending):
return False
return (name[-len(ending)-1::] == '.'+ending)
def is_file_blocked(name):
global ignore_platforms
for platform in ignore_platforms:
if (name.find(platform) != -1):
return True
for bit in ignore_bits:
if (name.find(bit) != -1):
return True
return False
for path, subdirs, files in os.walk("../kernel/kernel"):
for name in files:
# It runs from out dir, at least it should
file = "//" + path[3:] + "/" + name
if not is_file_type(file, 'c') and not is_file_type(file, 's') and not is_file_type(file, 'S'):
continue
if is_file_blocked(file):
continue
print(file)
def special_paths(platform):
pass
special_paths(target)

View File

@@ -0,0 +1,60 @@
_pa_base = 0x0;
_va_base = 0xffff800000000000;
ENTRY(_va_base)
SECTIONS
{
. = _va_base;
__text_start = .;
.text ALIGN(4K) :
{
*(.xos_kernel_boot)
*(.text)
*(.text.*)
}
__text_end = .;
__rodata_start = .;
.rodata ALIGN(4K) :
{
*(.rodata)
*(.rodata.*)
}
.rodata.driver_init ALIGN(4K) :
{
_drivers_init_start = .;
*(SORT_BY_NAME(.driver_init_sections.*))
_drivers_init_end = .;
}
__rodata_end = .;
__data_start = .;
.data ALIGN(4K) :
{
*(.data)
*(.data.*)
}
__data_end = .;
__bss_start = .;
.bss ALIGN(4K) :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
__bss_end = .;
__stack_start = .;
.stack ALIGN(4K) :
{
STACK_BASE = .;
. += 0x1000;
STACK_TOP = .;
}
__stack_end = .;
__end = .;
}

View File

@@ -0,0 +1,60 @@
_pa_base = 1M;
_va_base = 0xc0000000;
ENTRY(_va_base)
SECTIONS
{
. = _va_base;
__text_start = .;
.text ALIGN(4K) : AT (ADDR(.text) - _va_base + _pa_base)
{
*(.xos_kernel_boot)
*(.text)
*(.text.*)
}
__text_end = .;
__rodata_start = .;
.rodata ALIGN(4K) : AT (ADDR(.rodata) - _va_base + _pa_base)
{
*(.rodata)
*(.rodata.*)
}
.rodata.driver_init ALIGN(4K) : AT (ADDR(.rodata.driver_init) - _va_base + _pa_base)
{
_drivers_init_start = .;
*(SORT_BY_NAME(.driver_init_sections.*))
_drivers_init_end = .;
}
__rodata_end = .;
__data_start = .;
.data ALIGN(4K) : AT (ADDR(.data) - _va_base + _pa_base)
{
*(.data)
*(.data.*)
}
__data_end = .;
__bss_start = .;
.bss ALIGN(4K) : AT (ADDR(.bss) - _va_base + _pa_base)
{
*(.bss)
*(.bss.*)
*(COMMON)
}
__bss_end = .;
__stack_start = .;
.stack ALIGN(4K) : AT (ADDR(.stack) - _va_base + _pa_base)
{
STACK_BASE = .;
. += 0x1000;
STACK_TOP = .;
}
__stack_end = .;
__end = .;
}

View File

@@ -0,0 +1,60 @@
_pa_base = 0x0;
_va_base = 0xffff800000000000;
ENTRY(_va_base)
SECTIONS
{
. = _va_base;
__text_start = .;
.text ALIGN(4K) :
{
*(.xos_kernel_boot)
*(.text)
*(.text.*)
}
__text_end = .;
__rodata_start = .;
.rodata ALIGN(4K) :
{
*(.rodata)
*(.rodata.*)
}
.rodata.driver_init ALIGN(4K) :
{
_drivers_init_start = .;
*(SORT_BY_NAME(.driver_init_sections.*))
_drivers_init_end = .;
}
__rodata_end = .;
__data_start = .;
.data ALIGN(4K) :
{
*(.data)
*(.data.*)
}
__data_end = .;
__bss_start = .;
.bss ALIGN(4K) :
{
*(.bss)
*(.bss.*)
*(COMMON)
}
__bss_end = .;
__stack_start = .;
.stack ALIGN(4K) :
{
STACK_BASE = .;
. += 0x1000;
STACK_TOP = .;
}
__stack_end = .;
__end = .;
}

123
build/libs/BUILD.gn Normal file
View File

@@ -0,0 +1,123 @@
lib_c_flags = [
"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
]
if (userland_symbols) {
lib_c_flags += [ "-ggdb" ]
}
if (optimize) {
lib_c_flags += [ "-Os" ]
}
lib_cc_flags = [
"-std=c++2a",
"-fno-sized-deallocation",
"-fno-exceptions",
"-D_LIBCXX_BUILD_XOS_EXTENSIONS",
]
lib_objcc_flags = lib_cc_flags + [
"-Wno-nullability-completeness",
"-Wno-deprecated-objc-isa-usage",
"-Wno-objc-root-class",
"-Wno-cast-of-sel-type",
"-fno-objc-exceptions",
"-fno-objc-arc",
"-fno-unwind-tables",
]
lib_asm_flags = []
if (device_type == "desktop") {
lib_c_flags += [ "-DTARGET_DESKTOP" ]
}
if (device_type == "mobile") {
lib_c_flags += [ "-DTARGET_MOBILE" ]
}
if (target_arch == "x86") {
lib_asm_flags += [
"-f",
"elf",
]
}
if (target_arch == "x86_64") {
lib_asm_flags += [
"-f",
"elf64",
]
}
if (target_arch == "arm32") {
lib_c_flags += [
"-fno-builtin",
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=softfp",
"-fno-pie",
]
lib_asm_flags += [
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=softfp",
"-mcpu=cortex-a15",
]
}
if (target_arch == "arm64") {
lib_c_flags += [
"-fno-builtin",
"-mcpu=cortex-a53+nocrypto+nocrc",
"-fno-pie",
]
lib_asm_flags += [ "-mcpu=cortex-a53+nocrypto+nocrc" ]
}
if (target_arch == "riscv64") {
lib_c_flags += [
"-fno-builtin",
"-march=rv64ima",
"-mabi=lp64",
"-fno-pie",
]
lib_asm_flags += [
"-march=rv64ima",
"-mabi=lp64",
]
}
config("lib_flags") {
cflags = lib_c_flags
asmflags = lib_asm_flags
}
config("libobjcc_flags") {
cflags = lib_c_flags
cflags_objcc = lib_objcc_flags
cflags_cc = lib_cc_flags
asmflags = lib_asm_flags
}
config("libcxx_flags") {
cflags = lib_c_flags
asmflags = lib_asm_flags
cflags_cc = lib_cc_flags
}
group("libs") {
deps = [
"//libs/libc:libc",
"//libs/libcxx:libcxx",
"//libs/libfoundation:libfoundation",
"//libs/libg:libg",
"//libs/libui:libui",
]
if (objc_support) {
deps += [ "//libs/libobjc:libobjc" ]
}
}

102
build/libs/TEMPLATE.gni Normal file
View File

@@ -0,0 +1,102 @@
template("xOS_static_library") {
assert(defined(invoker.sources),
"Need sources in $target_name to build static library")
lib_name = target_name
lib_build_name = lib_name + "_build"
lib_include_config_name = lib_name + "_include_config"
compiled_lib_output_name_base = "$root_out_dir/tmp/libs/"
compiled_lib_output_name = compiled_lib_output_name_base + lib_name
final_lib_output_name = "$root_out_dir/base/libs/" + lib_name + ".a"
building_deplib_bulders_list = []
linking_deplib_bulders_list = []
linking_deplib_list = []
includes = []
if (defined(invoker.include_dirs)) {
includes = invoker.include_dirs
}
if (defined(invoker.deplibs)) {
foreach(i, invoker.deplibs) {
fullname = "//libs/" + i + ":" + i
# To speed up compilation we have separate deps for builing and linking stages.
# The only library which is required to be a dependancy for building stage is libfreetype,
# since its header files might not be available initially (they are archived).
if (i == "libfreetype") {
building_deplib_bulders_list += [ fullname + "_build" ]
}
linking_deplib_bulders_list += [ fullname + "_build" ]
linking_deplib_list += [ compiled_lib_output_name_base +
get_label_info(fullname, "name") + ".a" ]
includes += [ "//libs/" + i + "/include" ]
# Also adding libc includes.
# Note to add libc after libcxx.
if (i == "libcxx") {
includes += [ "//libs/libc/include" ]
}
# LibAPI is a lightweight library to use shared headers with API between libs and apps.
if (i == "libui") {
includes += [ "//libs/libapi/include" ]
}
}
}
includes += [ "//libs/" + lib_name + "/include" ]
# The output library is passed at the end.
linking_deplib_list += [ compiled_lib_output_name + ".a" ]
linking_deplib_bulders_list += [ "//libs/" + lib_name + ":" + lib_build_name ]
# Use a strange __EMPTY_PATH_, empty string can't be passed as an arg.
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
script_args = [
"$target_arch",
"$host",
"$path_to_bins",
rebase_path("$final_lib_output_name", root_build_dir),
]
foreach(i, linking_deplib_list) {
script_args += [ rebase_path(i, root_build_dir) ]
}
config(lib_include_config_name) {
include_dirs = includes
}
# Create a build rule to compile only a lib with unresolved references from other libs
static_library(lib_build_name) {
output_name = "tmp/libs/" + lib_name
sources = invoker.sources
include_dirs = includes
deps = building_deplib_bulders_list
forward_variables_from(invoker,
[
"configs",
"cflags",
"cflags_c",
"cflags_cc",
"cflags_objc",
"cflags_objcc",
"asmflags",
"deps",
"public_deps",
])
}
action(lib_name) {
script = "//build/libs/merge_libs.py"
inputs = linking_deplib_list
outputs = [ "$final_lib_output_name" ]
deps = linking_deplib_bulders_list
args = script_args
}
}

83
build/libs/merge_libs.py Normal file
View File

@@ -0,0 +1,83 @@
import sys
import subprocess
import random
AR_TOOL = ""
arch = sys.argv[1]
host = sys.argv[2]
path_to_bins = sys.argv[3]
target_lib = sys.argv[4]
srcs_lib = list(sys.argv[5:])
if path_to_bins == "__EMPTY_PATH_":
path_to_bins = ""
if len(path_to_bins) != 0:
if path_to_bins[-1] != '/':
path_to_bins += "/"
if (arch == "arm32"):
if host == "gnu":
AR_TOOL = "{0}arm-none-eabi-ar".format(path_to_bins)
srcs_lib.append(
"../toolchains/gcc_runtime/10.2.1/arm-none-eabi-libgcc.a")
elif host == "llvm":
AR_TOOL = "{0}llvm-ar".format(path_to_bins)
srcs_lib.append(
"/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.builtins-arm.a")
elif (arch == "x86"):
if host == "gnu":
AR_TOOL = "{0}i686-elf-ar".format(path_to_bins)
elif host == "llvm":
AR_TOOL = "{0}llvm-ar".format(path_to_bins)
srcs_lib.append(
"/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.builtins-i386.a")
elif (arch == "x86_64"):
if host == "gnu":
AR_TOOL = "{0}x86_64-elf-ar".format(path_to_bins)
srcs_lib.append(
"../toolchains/gcc_runtime/10.2.1/x86_64-libgcc.a")
elif host == "llvm":
AR_TOOL = "{0}llvm-ar".format(path_to_bins)
elif (arch == "arm64"):
if host == "gnu":
AR_TOOL = "{0}aarch64-elf-ar".format(path_to_bins)
srcs_lib.append(
"../toolchains/gcc_runtime/10.2.1/aarch64-libgcc.a")
elif host == "llvm":
AR_TOOL = "{0}llvm-ar".format(path_to_bins)
else:
print("Unsupported host for arch {0}".format(host, arch))
exit(1)
elif (arch == "riscv64"):
if host == "gnu":
AR_TOOL = "{0}riscv64-unknown-elf-ar".format(path_to_bins)
srcs_lib.append(
"../toolchains/gcc_runtime/10.2.1/riscv64-libgcc.a")
elif host == "llvm":
AR_TOOL = "{0}llvm-ar".format(path_to_bins)
srcs_lib.append(
"../toolchains/gcc_runtime/10.2.1/riscv64-libgcc.a")
else:
print("Unsupported host for arch {0}".format(host, arch))
exit(1)
else:
print("Unsupported arch {0}".format(arch))
exit(1)
if (len(srcs_lib) == 1):
output = subprocess.check_output(
"cp {1} {0}".format(target_lib, srcs_lib[0]), shell=True)
else:
filename = "libmerger{0}.mri".format(random.randint(10000, 100000))
ffile = open(filename, "w")
ffile.write("CREATE {0}\n".format(target_lib))
for i in srcs_lib:
ffile.write("ADDLIB {0}\n".format(i))
ffile.write("SAVE\n")
ffile.write("END")
ffile.close()
output = subprocess.check_output(
"{0} -M <{1}".format(AR_TOOL, filename), shell=True)
output = subprocess.check_output("rm {0}".format(filename), shell=True)

11
build/makefile.configs Normal file
View File

@@ -0,0 +1,11 @@
# Sync config
# SET YOUR PATHS HERE
FUSE_EXT2 = fuse-ext2
MKFS_LINUX = mkfs
MKFS_MAC = /usr/local/opt/e2fsprogs/sbin/mkfs.ext2
MKFS = ${MKFS_MAC}
MOUNT_EXT2 = ${FUSE_EXT2}
# xOS boot config
DISK = one.img
BASE_DIR = base

View File

@@ -0,0 +1,16 @@
template("xOS_signexec") {
app_name = target_name
assert(defined(invoker.binpath), "Install path must be provided")
binpath = invoker.binpath
action("sign_$app_name") {
script = "//build/security/sign_executable.py"
inputs = [ "$root_out_dir/base/$binpath" ]
outputs = [ "$root_out_dir/tmp/$binpath.signed" ]
deps = [ ":$app_name" + "_build" ]
args = [
rebase_path("$root_out_dir/base/$binpath", root_build_dir),
rebase_path("$root_out_dir/tmp/$binpath.signed", ""),
]
}
}

View File

@@ -0,0 +1,18 @@
import sys
import os
import subprocess
from pathlib import Path
def shell(cmd, cwd=None):
return subprocess.check_output(cmd, shell=True, cwd=cwd).decode("ascii")
elffile_path = sys.argv[1]
stampfile_path = sys.argv[2]
run_from = os.getcwd() + '/../utils/crypto/'
elffile_path_abs = os.getcwd() + '/' + elffile_path
shell("python3 elfsign.py {0} --overwrite".format(elffile_path_abs), run_from)
Path(stampfile_path).touch()

16
build/test/BUILD.gn Normal file
View File

@@ -0,0 +1,16 @@
group("test") {
deps = []
# If we run test, let's include the entry point.
if (test_method == "tests") {
deps += [
"//test/kernel:test_kernel",
"//test/libc:test_libc",
"//test/runner:launch_server",
]
}
if (test_method == "bench") {
deps += [ "//test/bench:launch_server" ]
}
}

36
build/test/TEMPLATE.gni Normal file
View File

@@ -0,0 +1,36 @@
import("//build/userland/EXEC_TEMPLATE.gni")
template("xOS_test") {
app_name = string_replace(invoker.test_bundle, "/", "\$")
xOS_executable_template(app_name) {
install_path = "test_bin/"
forward_variables_from(invoker,
[
"sources",
"configs",
"deplibs",
"cflags",
"cflags_c",
"cflags_cc",
"cflags_objc",
"cflags_objcc",
"asmflags",
"ldflags",
"public_deps",
])
if (defined(invoker.cflags)) {
cflags = invoker.cflags
} else {
cflags = []
}
cflags += [
"-DTestMsg(x)=printf(\"[MSG] %s\n\", x);fflush(stdout);",
"-DTestErr(x)=printf(\"[MSG] %s\n\", x);fflush(stdout);exit(1)",
]
}
group(target_name) {
deps = [ ":$app_name" + "_build" ]
}
}

3
build/third_party/BUILD.gn vendored Normal file
View File

@@ -0,0 +1,3 @@
group("third_party") {
deps = [ "//build/third_party/tinysh:tinysh" ]
}

27
build/third_party/PY_BRIDGE.gni vendored Normal file
View File

@@ -0,0 +1,27 @@
import("//build/userland/USERLAND_FLAGS.gni")
import("//toolchains/COMPILERS.gni")
if (uland_ld_flags == []) {
port_ld_flags = [ "__EMPTY__" ]
} else {
port_ld_flags = uland_ld_flags
}
py_bridging_args = [
# outpath here is inserted
rebase_path("//", root_build_dir), # rootdir
"$target_arch", # target cpu
"$host", # host compiler
string_join(" ",
[
toolchain_ar,
toolchain_cc,
toolchain_cxx,
toolchain_ld,
toolchain_asm,
toolchain_target,
]), # compiler_toolchain
string_join(" ", uland_c_flags), # c_flags
string_join(" ", uland_cc_flags), # cc_flags
string_join(" ", port_ld_flags), # ld_flags
]

109
build/third_party/PortingTools.py vendored Normal file
View File

@@ -0,0 +1,109 @@
import os
import subprocess
import sys
from pathlib import Path
from git import Repo
class PortTools:
def __init__(self):
pass
@staticmethod
def set_env(name, val):
os.environ[name] = str(val)
@staticmethod
def run_command_impl(cmd, cwd="."):
result = subprocess.run(
cmd, stdout=subprocess.PIPE, shell=True, cwd=cwd)
return (result.stdout.decode("ascii"), result.returncode)
@staticmethod
def run_command(cmd, cwd="."):
return PortTools.run_command_impl(cmd, cwd)
@staticmethod
def apply_patch(location, patch_name):
src_dir = location+"/src"
if not os.path.exists(src_dir):
return ("", -1)
patch_path = location+"/patches/"+patch_name
if not os.path.exists(patch_path):
return ("", -1)
applied_patch_path = location+"/patches/.applied_"+patch_name
if os.path.exists(applied_patch_path):
return ("", 0)
cmd = ["patch"]
myinput = open(patch_path)
result = subprocess.run(
cmd, stdin=myinput, stdout=subprocess.PIPE, cwd=src_dir)
if result.returncode == 0:
Path(applied_patch_path).touch()
return (result.stdout.decode("ascii"), result.returncode)
@staticmethod
def clone_git(location, url):
src_dir = location+"/src"
if os.path.exists(src_dir):
return
Repo.clone_from(url, src_dir)
class StaticBuiler:
def check_libs_present(self, lib_name):
lib_desc = StaticBuiler.libs.get(lib_name, None)
if lib_desc is None:
return False
if not os.path.exists(lib_desc["bin"]):
return False
return True
def __init__(self, rootdir, srcdir, libs):
self.rootdir = rootdir
self.srcdir = srcdir
self.target_libs = libs
self.libs = {
"libc": {
"include": self.rootdir + "/libs/libc/include",
"bin": self.rootdir + "/out/base/libs/",
}
}
def libs_include_flags(self):
flags = ""
for lib_name in self.target_libs:
lib_desc = self.libs.get(lib_name, None)
assert(lib_desc is not None)
flags += "-I"
flags += lib_desc["include"] + " "
return flags
def libs_link_flags(self):
flags = " "
for lib_name in self.target_libs:
lib_desc = self.libs.get(lib_name, None)
assert(lib_desc is not None)
flags += "-L"
flags += lib_desc["bin"] + " "
flags += "-l" + lib_name[3:] + " "
return flags
def run_command(self, cmd_str):
return PortTools.run_command(cmd_str, self.srcdir)
def move_exec(self, execname, targetdir):
if not os.path.exists(targetdir):
os.makedirs(targetdir)
return self.run_command("mv {0} {1}".format(execname, targetdir))
if __name__ == '__main__':
pass

34
build/third_party/PyBridgingTools.py vendored Normal file
View File

@@ -0,0 +1,34 @@
import os
import subprocess
import sys
from pathlib import Path
class PyBridgingTools:
def __init__(self):
pass
@staticmethod
def build_descriptor():
# Fixup for runtime libs.
ldflags = sys.argv[8] + " " if sys.argv[8] != "__EMPTY__" else ""
ldflags = ldflags.replace("../toolchains/", "../../../toolchains/")
desc = {
"outpath": os.path.abspath(sys.argv[1]),
"rootdir": os.path.abspath(sys.argv[2]),
"target_arch": sys.argv[3],
"host": sys.argv[4],
"toolchain": {
"ar": sys.argv[5].split(" ")[0],
"cc": sys.argv[5].split(" ")[1],
"cxx": sys.argv[5].split(" ")[2],
"ld": sys.argv[5].split(" ")[3],
"asm": sys.argv[5].split(" ")[4],
"target": sys.argv[5].split(" ")[5],
},
"c_flags": sys.argv[6] + " " if sys.argv[6] != "__EMPTY__" else "",
"cc_flags": sys.argv[7] + " " if sys.argv[7] != "__EMPTY__" else "",
"ld_flags": ldflags,
}
return desc

11
build/third_party/tinysh/BUILD.gn vendored Normal file
View File

@@ -0,0 +1,11 @@
import("//build/third_party/PY_BRIDGE.gni")
gnstate = [ rebase_path("$root_out_dir/base/bin/tinysh", root_build_dir) ] +
py_bridging_args
action("tinysh") {
script = "//build/third_party/tinysh/package.py"
outputs = [ "$root_out_dir/base/bin/tinysh" ]
args = gnstate
deps = [ "//libs/libc:libc" ]
}

97
build/third_party/tinysh/package.py vendored Normal file
View File

@@ -0,0 +1,97 @@
# fmt: off
import sys
from os import path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
from PortingTools import *
from PyBridgingTools import *
# fmt: on
state = PyBridgingTools.build_descriptor()
class TinyshPackage:
version = "1.0"
name = "tinysh"
exec_name = "simple-c-shell"
rootdir = state["rootdir"]
target_dir = state["rootdir"] + "/third_party/tinysh"
url = "https://github.com/jmreyes/simple-c-shell.git"
def __init__(self):
pass
def clean(self):
src_dir = self.target_dir + "/src"
PortTools.run_command("rm -rf {0}".format(src_dir))
def has_build(self):
cache_location = self.target_dir + \
"/bin_{0}/".format(state['target_arch'])
file_in_cache = cache_location + TinyshPackage.exec_name
return os.path.exists(file_in_cache)
def download(self):
PortTools.clone_git(self.target_dir, self.url)
def apply_patches(self):
txt, err = PortTools.apply_patch(
self.target_dir, "0001-llvm_support.patch")
if err:
print(txt)
exit(1)
txt, err = PortTools.apply_patch(
self.target_dir, "0002-disable_unsupported.patch")
if err:
print(txt)
exit(1)
def build(self):
cache_location = self.target_dir + \
"/bin_{0}/".format(state['target_arch'])
file_in_cache = cache_location + TinyshPackage.exec_name
if self.has_build():
return
src_dir = self.target_dir + "/src"
builder = StaticBuiler(state["rootdir"], src_dir, libs=["libc"])
PortTools.set_env("CC", state["toolchain"]["cc"])
PortTools.set_env("LD", state["toolchain"]["ld"])
cflags = ""
ldflags = ""
if state["host"] == "llvm":
cflags += "-target " + state["toolchain"]["target"] + " "
cflags += state["c_flags"]
cflags += builder.libs_include_flags()
PortTools.set_env("CFLAGS", cflags)
ldflags += state["ld_flags"]
ldflags += builder.libs_link_flags()
PortTools.set_env("LDFLAGS", ldflags)
_, err = builder.run_command(
"make CC=\"$CC\" LD=\"$LD\" CFLAGS=\"$CFLAGS\" LDFLAGS=\"$LDFLAGS\"")
if err:
exit(1)
exepath = src_dir + "/" + TinyshPackage.exec_name
builder.move_exec(exepath, cache_location)
builder.run_command("make clean")
def bin_is_ready(self):
cache_location = self.target_dir + \
"/bin_{0}/".format(state['target_arch'])
file_in_cache = cache_location + TinyshPackage.exec_name
if os.path.exists(state["outpath"]):
return
os.symlink(file_in_cache, state["outpath"])
package = TinyshPackage()
if not package.has_build():
package.download()
package.apply_patches()
package.build()
package.bin_is_ready()

36
build/tools/BUILD.gn Normal file
View File

@@ -0,0 +1,36 @@
action("build_scripts") {
script = "build_scripts.py"
outputs = [
"$root_build_dir/build.sh",
"$root_build_dir/run.sh",
"$root_build_dir/sync.sh",
"$root_build_dir/all.sh",
]
args = [
target_arch,
target_board,
rebase_path("//", root_build_dir),
rebase_path("$root_build_dir", root_build_dir),
]
}
# Use a strange __EMPTY_PATH_, empty string can't be passed as an arg.
path_to_bins = "__EMPTY_PATH_"
if (host == "llvm") {
path_to_bins = llvm_bin_path
}
prepare_env_script_args = [
rebase_path("$root_out_dir/tmp/elfsign_section.o", root_build_dir),
"$target_arch",
"$target_board",
"$host",
"$path_to_bins",
]
action("prepare_env") {
script = "prepare_env.py"
outputs = [ "$root_build_dir/tmp/elfsign_section.o" ]
args = prepare_env_script_args
}

View File

@@ -0,0 +1,190 @@
import sys
import os
QEMU_PATH_VAR = "qemu_exec"
QEMU_PATH_ENV_VAR = ""
QEMU_SMP_VAR = "qemu_smp"
QEMU_SMP_ENV_VAR = "XOS_QEMU_SMP"
QEMU_STD_PATH = ""
qemu_run_cmd = ""
arch = sys.argv[1]
target_board = sys.argv[2]
base = sys.argv[3]
out = sys.argv[4]
if arch == "x86":
QEMU_PATH_ENV_VAR = "XOS_QEMU_X86"
QEMU_STD_PATH = "qemu-system-i386"
qemu_run_cmd = "${2} -m 256M --drive file={1}/os-image.bin,format=raw,index=0,if=floppy -device piix3-ide,id=ide -drive id=disk,format=raw,file={1}/one.img,if=none -device ide-hd,drive=disk,bus=ide.0 -serial mon:stdio -rtc base=utc -vga std -qmp unix:./qmp-sock,server,nowait".format(
base, out, QEMU_PATH_VAR)
if arch == "x86_64":
QEMU_PATH_ENV_VAR = "XOS_QEMU_X86_64"
QEMU_STD_PATH = "qemu-system-x86_64"
qemu_run_cmd = "${2} -m 1G -kernel {1}/rawImage.elf -cpu phenom -device piix3-ide,id=ide -drive id=disk,format=raw,file={1}/one.img,if=none -device ide-hd,drive=disk,bus=ide.0 -serial mon:stdio -rtc base=utc -vga std".format(
base, out, QEMU_PATH_VAR)
if arch == "arm32":
QEMU_PATH_ENV_VAR = "XOS_QEMU_ARM"
QEMU_STD_PATH = "qemu-system-arm"
qemu_run_cmd = "${2} -m 256M -M vexpress-a15 -cpu cortex-a15 -kernel {1}/bootarm.bin -smp ${3} -serial mon:stdio -vga std -drive id=disk,if=sd,format=raw,file={1}/one.img".format(
base, out, QEMU_PATH_VAR, QEMU_SMP_VAR)
if arch == "arm64":
QEMU_PATH_ENV_VAR = "XOS_QEMU_AA64"
QEMU_STD_PATH = "echo Please provide path to custom QEMU with $XOS_QEMU_AA64, see https://code.ayaantunio.me/ayaan/Custom-Operating-System/src/branch/master/docs/getting_qemu.md"
qemu_run_cmd = "${2} -machine virt,secure=off,virtualization=off,gic-version=2 -cpu cortex-a53 -m 1G -kernel {1}/rawImage.bin -smp ${3} -serial mon:stdio -drive id=disk,if=sd,format=raw,file={1}/one.img".format(
base, out, QEMU_PATH_VAR, QEMU_SMP_VAR)
if target_board == "apl":
qemu_run_cmd = "python3 {0}/utils/codeassistant/pongo_startup.py".format(base)
if arch == "riscv64":
QEMU_PATH_ENV_VAR = "XOS_QEMU_RV64"
QEMU_STD_PATH = "qemu-system-riscv64"
qemu_run_cmd = "${2} -machine virt -m 1G -bios none -kernel {1}/prekernelriscv64.bin -serial mon:stdio -drive if=none,format=raw,file={1}/one.img,id=drv -device virtio-blk-device,drive=drv -device virtio-rng-device -device virtio-gpu-device -device virtio-keyboard-device -device virtio-mouse-device".format(
base, out, QEMU_PATH_VAR, QEMU_SMP_VAR)
if base[-1] == '/':
base = base[:-1]
if out[-1] == '/':
out = out[:-1]
env_var_checker = """
{2}="{3}"
{4}=1
[[ -z "${1}" ]] && {2}='{3}' || {2}="${1}"
[[ -z "${5}" ]] && {4}=1 || {4}="${5}"
""".format("", QEMU_PATH_ENV_VAR, QEMU_PATH_VAR, QEMU_STD_PATH, QEMU_SMP_VAR, QEMU_SMP_ENV_VAR)
sync = open("{0}/sync.sh".format(out), "w")
sync.write(
"""#!/bin/bash
GREEN='\\033[0;32m'
RED='\\033[0;31m'
NC='\\033[0m'
ERROR="${{RED}}[ERROR]${{NC}}"
SUCCESS="${{GREEN}}[SUCCESS]${{NC}}"
mkdir -p {1}/mountpoint
sudo fuse-ext2 {1}/one.img {1}/mountpoint -o rw+
if [ $? -ne 0 ]; then echo -e "${{ERROR}} Can't mount one.img to {1}/mountpoint" && exit 1; fi
sudo mkdir -p {1}/mountpoint/boot
sudo mkdir -p {1}/mountpoint/proc
sudo mkdir -p {1}/mountpoint/var
sudo mkdir -p {1}/mountpoint/dev
sudo mkdir -p {1}/mountpoint/tmp
sudo cp -r {0}/base/* {1}/mountpoint/
sudo cp -r {1}/base/* {1}/mountpoint/
sudo chmod -R 644 {1}/mountpoint/proc
sudo chmod -R 644 {1}/mountpoint/dev
sudo chmod -R 666 {1}/mountpoint/tmp
sudo chmod -R 666 {1}/mountpoint/var
sudo chmod -R 755 {1}/mountpoint/bin
sudo chmod -R 700 {1}/mountpoint/home
sudo chmod 777 {1}/mountpoint/home
sudo chmod -R 755 {1}/mountpoint/System
sudo chmod -R 755 {1}/mountpoint/Applications
sudo chown -R 0 {1}/mountpoint/home/root
sudo chown -R 0 {1}/mountpoint/bin/sudo
sudo chmod 4755 {1}/mountpoint/bin/sudo
sudo chown -R 10 {1}/mountpoint/home/user
sudo umount {1}/mountpoint
if [ $? -ne 0 ]; then echo -e "${{ERROR}} Can't umount {1}/mountpoint" && exit 1; fi
echo -e "${{SUCCESS}} Sync"
""".format(base, out))
sync.close()
build = open("{0}/build.sh".format(out), "w")
build.write(
"""#!/bin/bash
GREEN='\\033[0;32m'
RED='\\033[0;31m'
NC='\\033[0m'
ERROR="${{RED}}[ERROR]${{NC}}"
SUCCESS="${{GREEN}}[SUCCESS]${{NC}}"
ninja
if [ $? -ne 0 ]; then echo -e "${{ERROR}} Can't build for arch: {0}" && exit 1; fi
echo -e "${{SUCCESS}} Build for arch: {0}"
""".format(arch))
build.close()
run = open("{0}/run.sh".format(out), "w")
run.write(
"""#!/bin/bash
{1}
{0}
if [ $? -ne 0 ]; then echo -e "${{ERROR}} Run command failed" && exit 1; fi""".format(qemu_run_cmd, env_var_checker)
)
run.close()
debug = open("{0}/debug.sh".format(out), "w")
debug.write(
"""#!/bin/bash
{1}
{0} -s -S
if [ $? -ne 0 ]; then echo -e "${{ERROR}} Debug Run command failed" && exit 1; fi""".format(qemu_run_cmd, env_var_checker)
)
debug.close()
allf = open("{0}/all.sh".format(out), "w")
allf.write(
"""#!/bin/bash
GREEN='\\033[0;32m'
RED='\\033[0;31m'
NC='\\033[0m'
ERROR="${RED}[ERROR]${NC}"
SUCCESS="${GREEN}[SUCCESS]${NC}"
./build.sh
if [ $? -ne 0 ]; then echo -e "${ERROR} All command failed" && exit 1; fi
./sync.sh
if [ $? -ne 0 ]; then echo -e "${ERROR} All command failed" && exit 1; fi
./run.sh
if [ $? -ne 0 ]; then echo -e "${ERROR} All command failed" && exit 1; fi
""")
allf.close()
allf = open("{0}/run_tester.sh".format(out), "w")
allf.write(
"""#!/bin/bash
GREEN='\\033[0;32m'
RED='\\033[0;31m'
NC='\\033[0m'
ERROR="${{RED}}[ERROR]${{NC}}"
SUCCESS="${{GREEN}}[SUCCESS]${{NC}}"
./build.sh
if [ $? -ne 0 ]; then echo -e "${{ERROR}} All command failed" && exit 1; fi
./sync.sh
if [ $? -ne 0 ]; then echo -e "${{ERROR}} All command failed" && exit 1; fi
{1}
{0} --nographic
if [ $? -ne 0 ]; then echo -e "${{ERROR}} All command failed" && exit 1; fi
""".format(qemu_run_cmd, env_var_checker))
allf.close()
allf = open("{0}/dll.sh".format(out), "w")
allf.write(
"""#!/bin/bash
GREEN='\\033[0;32m'
RED='\\033[0;31m'
NC='\\033[0m'
ERROR="${RED}[ERROR]${NC}"
SUCCESS="${GREEN}[SUCCESS]${NC}"
./build.sh
if [ $? -ne 0 ]; then echo -e "${ERROR} Debug All command failed" && exit 1; fi
./sync.sh
if [ $? -ne 0 ]; then echo -e "${ERROR} Debug All command failed" && exit 1; fi
./debug.sh
if [ $? -ne 0 ]; then echo -e "${ERROR} Debug All command failed" && exit 1; fi
""")
allf.close()
gdbinit = open("{0}/.gdbinit".format(out), "w")
gdbinit.write(
"""file {0}/base/boot/kernel.bin
target remote :1234""".format(out))
gdbinit.close()

View File

@@ -0,0 +1,78 @@
import sys
import os
import subprocess
OBJCOPY_TOOL = ""
OBJCOPY_TARGET = ""
def shell(cmd, cwd=None):
return subprocess.check_output(cmd, shell=True, cwd=cwd).decode("ascii")
outpath = sys.argv[1]
arch = sys.argv[2]
board = sys.argv[3]
host = sys.argv[4]
path_to_bins = sys.argv[5]
if path_to_bins == "__EMPTY_PATH_":
path_to_bins = ""
if len(path_to_bins) != 0:
if path_to_bins[-1] != '/':
path_to_bins += "/"
if (arch == "arm32"):
if host == "gnu":
OBJCOPY_TOOL = "{0}arm-none-eabi-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf32-littlearm"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf32-littlearm"
elif (arch == "x86"):
if host == "gnu":
OBJCOPY_TOOL = "{0}i686-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf32-i386"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf32-i386"
elif (arch == "x86_64"):
if host == "gnu":
OBJCOPY_TOOL = "{0}x86_64-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-x86-64"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-x86-64"
elif (arch == "arm64"):
if host == "gnu":
OBJCOPY_TOOL = "{0}aarch64-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleaarch64"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleaarch64"
elif (arch == "riscv64"):
if host == "gnu":
OBJCOPY_TOOL = "{0}riscv64-unknown-elf-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleriscv"
elif host == "llvm":
OBJCOPY_TOOL = "{0}llvm-objcopy".format(path_to_bins)
OBJCOPY_TARGET = "elf64-littleriscv"
else:
print("Unsupported arch {0}".format(arch))
exit(0)
outpath_abs = os.getcwd() + '/' + outpath
codesign_section_len = 1024
tmp_empty_bin_name = 'elfsign_section.bin'
f = open(tmp_empty_bin_name, "wb")
f.seek(codesign_section_len-1)
f.write(b"\0")
f.close()
shell("{0} -I binary -O {1} --rename-section .data=._signature {2} {3}".format(
OBJCOPY_TOOL, OBJCOPY_TARGET, tmp_empty_bin_name, outpath_abs))
shell("{0} --set-section-flags ._signature=noload,readonly {1} {2}".format(
OBJCOPY_TOOL, outpath_abs, outpath_abs))

73
build/userland/BUILD.gn Normal file
View File

@@ -0,0 +1,73 @@
import("//build/userland/USERLAND_FLAGS.gni")
config("userland_flags") {
cflags = uland_c_flags
cflags_cc = uland_cc_flags
cflags_objcc = uland_objcc_flags
asmflags = uland_asm_flags
ldflags = uland_ld_flags
defines = [ "xOS" ]
}
group("applications") {
deps = [
"//userland/applications/about:about",
"//userland/applications/activity_monitor:activity_monitor",
"//userland/applications/calculator:calculator",
"//userland/applications/terminal:terminal",
]
}
group("system") {
deps = [
"//userland/system/applist:applist",
"//userland/system/dock:dock",
"//userland/system/homescreen:homescreen",
]
}
group("servers") {
deps = [ "//userland/servers/window_server:window_server" ]
}
group("utilities") {
deps = [
"//userland/utilities/cat:cat",
"//userland/utilities/kill:kill",
"//userland/utilities/ls:ls",
"//userland/utilities/mkdir:mkdir",
"//userland/utilities/rm:rm",
"//userland/utilities/rmdir:rmdir",
"//userland/utilities/sudo:sudo",
"//userland/utilities/touch:touch",
"//userland/utilities/uname:uname",
"//userland/utilities/whoami:whoami",
]
}
group("userland") {
deps = [
"//build/userland:applications",
"//build/userland:servers",
"//build/userland:system",
"//build/userland:utilities",
"//userland/shell/xsh:xsh",
]
# Make sure that we don't run any tests/benchmarks, since
# tests/benchmarks use thier own entry point.
if (test_method == "none") {
deps += [ "//userland/servers/launch_server:launch_server" ]
}
if (compile_tests) {
deps += [
"//userland/tests/testlibcxx:testlibcxx",
"//userland/tests/utester:utester",
]
if (objc_support) {
deps += [ "//userland/tests/testobjc:testobjc" ]
}
}
}

View File

@@ -0,0 +1,77 @@
template("xOS_executable_template") {
assert(defined(invoker.sources),
"Need sources in $target_name to build xOS App")
app_name = target_name
app_build_name = app_name + "_build"
deplibs = []
depbuilders = []
includes = []
confs = []
if (defined(invoker.libs)) {
deplibs = invoker.libs
}
if (defined(invoker.deps)) {
depbuilders = invoker.deps
}
if (defined(invoker.include_dirs)) {
includes = invoker.include_dirs
}
if (defined(invoker.configs)) {
confs = invoker.configs
}
if (defined(invoker.deplibs)) {
foreach(i, invoker.deplibs) {
deplibs += [ "$root_out_dir/base/libs/" + i + ".a" ]
depbuilders += [ "//libs/" + i + ":" + i ]
includes += [ "//libs/" + i + "/include" ]
confs += [ "//libs/" + i + ":" + i + "_include_config" ]
# Also adding libc includes.
# Note to add libc after libcxx.
if (i == "libcxx") {
includes += [ "//libs/libc/include" ]
}
if (i == "libui") {
includes += [ "//libs/libapi/include" ]
}
}
}
linkflags = []
if (defined(invoker.need_sign_section) && invoker.need_sign_section == true) {
# Adding empty section for a signature.
# HACK: Since ldflags follow inputs for linker we put this
# section as a first flag, but it will be treated as input.
linkflags += [ rebase_path("$root_out_dir/tmp/elfsign_section.o", "") ]
}
if (defined(invoker.ldflags)) {
linkflags += invoker.ldflags
}
executable(app_build_name) {
if (defined(invoker.install_path)) {
output_name = "base/" + invoker.install_path + app_name
} else {
output_name = "base/bin/" + app_name
}
sources = invoker.sources
libs = deplibs
deps = depbuilders
include_dirs = includes
configs = confs
ldflags = linkflags
forward_variables_from(invoker,
[
"cflags",
"cflags_c",
"cflags_cc",
"cflags_objc",
"cflags_objcc",
"asmflags",
"public_deps",
])
}
}

View File

@@ -0,0 +1,94 @@
import("//build/security/SIGN_TEMPLATE.gni")
import("//build/userland/EXEC_TEMPLATE.gni")
template("xOS_executable") {
app_name = target_name
assert(defined(invoker.install_path), "Install path must be provided")
signexec = false
if (defined(invoker.signexec)) {
signexec = invoker.signexec
}
if (signexec) {
xOS_signexec(app_name) {
binpath = invoker.install_path + app_name
}
}
xOS_executable_template(app_name) {
need_sign_section = signexec
forward_variables_from(invoker,
[
"install_path",
"sources",
"configs",
"deplibs",
"cflags",
"cflags_c",
"cflags_cc",
"cflags_objc",
"cflags_objcc",
"asmflags",
"ldflags",
"public_deps",
"include_dirs",
])
}
group(app_name) {
deps = [ ":$app_name" + "_build" ]
if (signexec) {
deps += [ ":sign_" + "$app_name" ]
}
}
}
template("xOS_application") {
app_name = target_name
root = "Applications/$app_name.app"
exec_file = "$root/Content/"
action("prepare_$app_name") {
script = "//build/userland/prepare_app.py"
outputs = [ "$root_out_dir/base/Applications/$app_name.app/Content" ]
args = [
app_name,
invoker.display_name,
rebase_path("$root_out_dir/base/Applications/$app_name.app/Content",
root_build_dir),
rebase_path("//userland/applications/$app_name", root_build_dir),
]
}
xOS_signexec(app_name) {
binpath = exec_file + app_name
}
xOS_executable_template(app_name) {
install_path = "$exec_file"
need_sign_section = true
forward_variables_from(invoker,
[
"sources",
"configs",
"deplibs",
"cflags",
"cflags_c",
"cflags_cc",
"asmflags",
"ldflags",
"public_deps",
"include_dirs",
])
}
group(app_name) {
deps = [
":$app_name" + "_build",
":prepare_$app_name",
":sign_" + "$app_name",
]
}
}

View File

@@ -0,0 +1,140 @@
uland_c_flags = [
"-Werror",
"-Wno-address-of-packed-member",
]
if (userland_symbols) {
uland_c_flags += [ "-ggdb" ]
}
if (optimize) {
uland_c_flags += [ "-Os" ]
}
uland_cc_flags = [
"-std=c++2a",
"-fno-sized-deallocation",
"-fno-exceptions",
"-D_LIBCXX_BUILD_XOS_EXTENSIONS",
]
uland_objcc_flags = uland_cc_flags + [
"-fno-objc-exceptions",
"-fno-objc-arc",
]
uland_asm_flags = []
uland_ld_flags = []
if (device_type == "desktop") {
uland_c_flags += [ "-DTARGET_DESKTOP" ]
}
if (device_type == "mobile") {
uland_c_flags += [ "-DTARGET_MOBILE" ]
}
if (target_arch == "x86") {
uland_asm_flags += [
"-f",
"elf",
]
}
if (target_arch == "x86_64") {
uland_asm_flags += [
"-f",
"elf64",
]
}
if (target_arch == "arm32") {
uland_c_flags += [
"-fno-builtin",
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=softfp",
"-fno-pie",
]
uland_asm_flags += [
"-march=armv7-a",
"-mfpu=neon-vfpv4",
"-mfloat-abi=softfp",
"-mcpu=cortex-a15",
]
uland_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
uland_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
uland_ld_flags += [
"--oformat",
"elf32-littlearm",
"/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.builtins-arm.a",
]
}
}
if (target_arch == "arm64") {
uland_c_flags += [
"-fno-builtin",
"-mcpu=cortex-a53+nocrypto+nocrc",
"-fno-pie",
]
uland_asm_flags += [ "-mcpu=cortex-a53+nocrypto+nocrc" ]
uland_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
uland_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
"-lgcc",
]
}
if (host == "llvm") {
uland_ld_flags += [
"--oformat",
"elf64-littlearm",
]
}
}
if (target_arch == "riscv64") {
uland_c_flags += [
"-fno-builtin",
"-march=rv64ima",
"-mabi=lp64",
]
uland_asm_flags += [
"-march=rv64ima",
"-mabi=lp64",
]
uland_ld_flags += [ "-nostdlib" ]
if (host == "gnu") {
uland_ld_flags += [
"-nostdinc",
"-nodefaultlibs",
"-nostartfiles",
rebase_path("//toolchains/gcc_runtime/10.2.1/riscv64-libgcc.a",
root_build_dir),
]
}
if (host == "llvm") {
uland_ld_flags += [
"--oformat",
"elf64",
rebase_path("//toolchains/gcc_runtime/10.2.1/riscv64-libgcc.a",
root_build_dir),
]
}
}

View File

@@ -0,0 +1,44 @@
import sys
import os
import json
import subprocess
fs_app_name = sys.argv[1]
app_name = sys.argv[2]
outpath = sys.argv[3]
src_dir = sys.argv[4]
def print_json(config_file, rdict):
json.dump(rdict, config_file, indent=4)
def read_config(path):
with open(path) as json_file:
data = json.load(json_file)
return data
return {}
def write_config(config, outpath):
config_file = open(outpath+"/info.json", "w")
config['name'] = app_name
config['exec_rel_path'] = fs_app_name
config['icon_path'] = "/res/icons/apps/" + fs_app_name + ".icon"
config['bundle_id'] = "com.x.{0}".format(fs_app_name)
print_json(config_file, config)
config_file.close()
if not os.path.exists(outpath):
os.makedirs(outpath)
config = {}
for fname in os.listdir(src_dir):
if fname == "info.json":
config = read_config(src_dir + "/info.json")
break
write_config(config, outpath)