mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Bonnibel will now build dynamic libraries when they're dependencies for non-statically linked modules. It will also copy those shared libraries into the initrd image for programs being copied into the image.
133 lines
4.0 KiB
Python
133 lines
4.0 KiB
Python
from . import BonnibelError
|
|
|
|
class Manifest:
|
|
from collections import namedtuple
|
|
Entry = namedtuple("Entry", ("module", "target", "output", "flags"))
|
|
|
|
flags = {
|
|
"graphical": 0x01,
|
|
"symbols": 0x80,
|
|
}
|
|
|
|
boot_flags = {
|
|
"debug": 0x01,
|
|
"test": 0x02,
|
|
}
|
|
|
|
def __init__(self, path, modules):
|
|
from . import load_config
|
|
|
|
config = load_config(path)
|
|
|
|
self.location = config.get("location", "jsix")
|
|
|
|
self.kernel = self.__build_entry(modules,
|
|
config.get("kernel", dict()),
|
|
name="kernel", target="kernel")
|
|
|
|
self.init = self.__build_entry(modules,
|
|
config.get("init", None), target="init")
|
|
|
|
self.panics = [self.__build_entry(modules, i, target="kernel")
|
|
for i in config.get("panic", tuple())]
|
|
|
|
self.services = [self.__build_entry(modules, i)
|
|
for i in config.get("services", tuple())]
|
|
|
|
self.drivers = [self.__build_entry(modules, i)
|
|
for i in config.get("drivers", tuple())]
|
|
|
|
libs = set(config.get("libs", tuple()))
|
|
libs.update(self.__libdeps([modules[e.module] for e in self.services]))
|
|
libs.update(self.__libdeps([modules[e.module] for e in self.drivers]))
|
|
|
|
self.libs = [self.__build_entry(modules, i)
|
|
for i in libs]
|
|
|
|
self.flags = config.get("flags", tuple())
|
|
|
|
self.symbols = ""
|
|
|
|
initrd = config.get("initrd", dict())
|
|
self.initrd = {
|
|
"name": initrd.get("name", "initrd.dat"),
|
|
"format": initrd.get("format", "zstd"),
|
|
}
|
|
|
|
self.data = []
|
|
for d in config.get("data", tuple()):
|
|
self.add_data(**d)
|
|
|
|
def __build_entry(self, modules, config, target="user", name=None):
|
|
flags = tuple()
|
|
|
|
if isinstance(config, str):
|
|
name = config
|
|
elif isinstance(config, dict):
|
|
name = config.get("name", name)
|
|
target = config.get("target", target)
|
|
flags = config.get("flags", tuple())
|
|
if isinstance(flags, str):
|
|
flags = flags.split()
|
|
|
|
mod = modules.get(name)
|
|
if not mod:
|
|
raise BonnibelError(f"Manifest specifies unknown module '{name}'")
|
|
|
|
for f in flags:
|
|
if not f in Manifest.flags:
|
|
raise BonnibelError(f"Manifest specifies unknown flag '{f}'")
|
|
|
|
return Manifest.Entry(name, target, mod.get_output(), flags)
|
|
|
|
def __libdeps(self, modules):
|
|
deps = set([m.name for m in modules if m.kind == "lib"])
|
|
for m in modules:
|
|
if m.static: continue
|
|
deps.update(self.__libdeps(m.depmods))
|
|
return deps
|
|
|
|
def add_data(self, output, desc, flags=tuple()):
|
|
e = Manifest.Entry(None, None, output, flags)
|
|
self.data.append(e)
|
|
return e
|
|
|
|
def write_boot_config(self, path):
|
|
from os.path import join
|
|
import struct
|
|
|
|
with open(path, 'wb') as outfile:
|
|
magic = "jsixboot".encode("utf-8") # magic string
|
|
version = 1
|
|
|
|
bootflags = sum([Manifest.boot_flags.get(s, 0) for s in self.flags])
|
|
|
|
outfile.write(struct.pack("<8s BBH",
|
|
magic,
|
|
version, len(self.panics), bootflags))
|
|
|
|
def write_str(s):
|
|
data = s.encode("utf-16le")
|
|
outfile.write(struct.pack("<H", len(data)+2))
|
|
outfile.write(data)
|
|
outfile.write(b"\0\0")
|
|
|
|
def write_path(name):
|
|
write_str(join(self.location, name).replace('/','\\'))
|
|
|
|
def write_ent(ent):
|
|
flags = 0
|
|
for f in ent.flags:
|
|
flags |= Manifest.flags[f]
|
|
|
|
outfile.write(struct.pack("<H", flags))
|
|
write_path(ent.output)
|
|
|
|
write_ent(self.kernel)
|
|
write_ent(self.init)
|
|
write_path(self.initrd["name"])
|
|
write_path(self.symbols)
|
|
|
|
for p in self.panics:
|
|
write_ent(p)
|