Merge pull request #334 from fosslinux/simplify

Simplify + Sustainability
This commit is contained in:
fosslinux 2023-12-15 11:54:29 +00:00 committed by GitHub
commit 545bb42ca8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
564 changed files with 2057 additions and 2011 deletions

View File

@ -21,7 +21,7 @@ jobs:
- name: Install pylint
run: sudo pip3 install pylint
- name: pylint
run: pylint rootfs.py sysa.py sysc.py lib/utils.py lib/sysgeneral.py lib/tmpdir.py --disable=duplicate-code
run: pylint rootfs.py lib/utils.py lib/generator.py lib/tmpdir.py --disable=duplicate-code
shellcheck:
name: Lint shell files
@ -30,7 +30,7 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v3
- name: shellcheck
run: shellcheck sysa/run.sh sysa/run2.sh sysb/init sysb/run.sh sysc/init sysc/run.sh sysa/helpers.sh download-distfiles.sh
run: shellcheck steps/helpers.sh download-distfiles.sh
reuse:
name: Lint reuse information

5
.gitignore vendored
View File

@ -5,7 +5,6 @@
tmp/
kernel
sysa/distfiles/
sysc/distfiles/
distfiles/
__pycache__
sysa/bootstrap.cfg
steps/bootstrap.cfg

7
.gitmodules vendored
View File

@ -2,7 +2,6 @@
# SPDX-FileCopyrightText: 2021 fosslinux <fosslinux@aussies.space>
#
# SPDX-License-Identifier: MIT
[submodule "sysa/stage0-posix/src"]
path = sysa/stage0-posix/src
url = https://github.com/oriansj/stage0-posix/
[submodule "seed/stage0-posix"]
path = seed/stage0-posix
url = https://github.com/oriansj/stage0-posix

View File

@ -9,6 +9,6 @@ Source: https://github.com/fosslinux/live-bootstrap
# Copyright: $YEAR $NAME <$CONTACT>
# License: ...
Files: sys*/*/sources sysa/*/*.checksums sysa/SHA256SUMS.pkgs sysa/*/simple-patches/*
Files: steps/*/sources steps/*/*.checksums steps/SHA256SUMS.pkgs steps/*/simple-patches/* steps/pre-network-sources
Copyright: none
License: MIT

View File

@ -14,31 +14,40 @@ and that a full build completes.
## Structure
Each system corresponds to a reboot of the live environment. There is only one
appropriate structure as shown below (eg for sysa):
```
sysa
├── any-global-files.sh
seed
├── seed.kaem
├── script-generator.c
├── ...
└── stage0-posix
steps
├── manifest
├── any-global-files
├── jump
│   └── linux.sh
├── improve
│   └── x.sh
├── somepackage-version
│   ├── somepackage-version.kaem (or .sh)
│   ├── pass1.kaem
│   ├── pass2.sh
│   ├── files
│   ├── simple-patches
│   ├── mk
│   └── patches
└── tmp
```
Global scripts that drive the entire system go directly under `sysx`. `tmp`
contains the temporary system used for QEMU or a chroot.
The `seed` directory contains everything required for `script-generator` to be
run.
Then, each package is in its own specific directory, named `package-version`.
It then diverges based upon which driver is being used:
- `kaem`: A file named `package-version.kaem` is called by the master script.
- `bash`: The `build` function from helper.sh is called from the master script.
There are default functions run which can be overridden by an optional script
`package-version.sh` within the package-specific directory.
In the `steps` directory, the bootstrap process is defined in `manifest`.
Each package to be built is named `package-version`.
Each subsequent build of a package is the nth pass. Scripts are named
accordingly; eg, the first build would be called `pass1.sh`, the second would be
`pass2.sh`, etc.
Scripts run in kaem era should be denoted as such in their filename;
`pass1.kaem`, for example. Pass numbers do not reset after kaem, ie, you cannot
have both `pass1.kaem` and `pass1.sh`.
In this folder, there are other folders/files. `*.checksums` are
required for early packages that are build with kaem, others are optional.
@ -51,21 +60,16 @@ Permissible folders/files:
- `simple-patches`: patches for the source that use the before/after convention of simple-patch.c
- `*.checksums`: files containing the checksums for the resulting binaries and
libraries that are compiled and installed.
- Up to and including `coreutils-6.10`, `sha256sum` from `stage0-posix`
is used for the checksumming. Later we switch to GNU version.
- To extract checksums of the binaries, use of qemu mode is recommended
(i.e. `./rootfs.py -q -qk $kernel --update-checksums`).
- compilation script
The directory m2-functions is used for M2-Planet functions (currently).
- Otherwise, the package's checksum is in SHA256SUMS.pkgs.
- compilation script(s)
## Conventions
- **Patches:**
- all patches are `-p0`
- all patches begin with a patch header
- **README:**
- all stages are explained in README
- **parts.rst:**
- all packages are explained in `parts.rst`
- **General:**
- Where possible, all blocks of text should be limited to a length of 80
characters.
@ -79,9 +83,3 @@ The directory m2-functions is used for M2-Planet functions (currently).
- Patches are licensed under the license of the project which they are
patching.
- All files (excluding files within submodules) must comply with REUSE v3.0.
## git
All changes must be submitted as PRs. Pushing to master is disallowed, even if
push access is granted to a user. Only pushes to master should be merging of
patches into master.

View File

@ -12,94 +12,90 @@ An attempt to provide a reproducible, automatic, complete end-to-end
bootstrap from a minimal number of binary seeds to a supported fully
functioning operating system.
Get me started!
---------------
How do I use this?
------------------
Quick start:
See ``./rootfs.py --help`` and follow the instructions given there.
This uses a variety of userland tools to prepare the bootstrap.
(*Currently, there is no way to perform the bootstrap without external
preparations! This is a currently unsolved problem.*)
Without using Python:
1. ``git clone https://github.com/fosslinux/live-bootstrap``
2. ``git submodule update --init --recursive``
3. Provide a kernel (vmlinuz file) as the name ``kernel`` in the root of the
repository. **This must be a 32-bit kernel.**
4. ``./rootfs.py --qemu`` - ensure your account has kvm privileges and qemu
installed.
a. Alternatively, run ``./rootfs.py --chroot`` to run it in a chroot.
b. Alternatively, run ``./rootfs.py --bwrap`` to run it in a bubblewrap
sandbox. When user namespaces are supported, this mode is rootless.
c. Alternatively, run ``./rootfs.py`` but dont run the actual
virtualization and instead copy sysa/tmp/initramfs to a USB or
some other device and boot from bare metal. NOTE: we now require
a hard drive. This is currently hardcoded as sda. You also need
to put ``sysc/tmp/disk.img`` onto your sda on the bootstrapping
machine.
d. Alternatively, do not use python at all, see "Python-less build"
below.
5. Wait.
6. If you can, observe the many binaries in ``/usr/bin``! When the
bootstrap is completed ``bash`` is launched providing a shell to
explore the system.
3. Consider whether you are going to run this in a chroot, in QEMU, or on bare
metal. (All of this *can* be automated, but not in a trustable way. See
further below.)
a. **chroot:** Create a directory where the chroot will reside, run
``./download-distfiles.sh``, and copy:
* The entire contents of ``seed/stage0-posix`` into that directory.
* All other files in ``seed`` into that directory.
* ``steps/`` and ``distfiles/`` into that directory.
* At least all files listed in ``steps/pre-network-sources`` must be
copied in. All other files will be obtained from the network.
* Run ``/bootstrap-seeds/POSIX/x86/kaem-optional-seed`` in the chroot.
(Eg, ``chroot rootfs /bootstrap-seeds/POSIX/x86/kaem-optional-seed``).
b. **QEMU:** Create two blank disk images.
* On the first image, write
``seed/stage0-posix/bootstrap-seeds/NATIVE/x86/builder-hex0-x86-stage1.img``
to it, followed by ``kernel-bootstrap/builder-hex0-x86-stage2.hex0``,
followed by zeros padding the disk to the next sector.
* distfiles can be obtained using ``./download-distfiles.sh``.
* See the list in part a. For every file within that list, write a line to
the disk ``src <size-of-file> <path-to-file>``, followed by the contents
of the file.
* *Only* copy distfiles listed in ``steps/pre-network-sources`` into
this disk.
* Optionally (if you don't do this, distfiles will be network downloaded):
* On the second image, create an MSDOS partition table and one ext3
partition.
* Copy ``distfiles/`` into this disk.
* Run QEMU, with 4+G RAM, optionally SMP (multicore), both drives (in the
order introduced above), a NIC with model E1000 (``-nic
user,model=e1000``), and ``-machine kernel-irqchip=split``.
c. **Bare metal:** Follow the same steps as QEMU, but the disks need to be
two different *physical* disks, and boot from the first disk.
Background
----------
This project is a part of the bootstrappable project, a project that
aims to be able to build complete computing platforms through the use of
source code. When you build a compiler like GCC, you need another C
compiler to compile the compiler - turtles all the way down. Even the
first GCC compiler was written in C. There has to be a way to break the
chain…
Problem statement
=================
There has been significant work on this over the last 5 years, from
Jeremiah Orians stage0, hex2 and M2-Planet to jannekes Mes. We have a
currently, fully-functioning chain of bootstrapping from the 357-byte
hex0 seed to a complete GCC compiler and hence a full Linux operating
system. From there, it is trivial to move to other UNIXes. However,
there is only currently one vector through which this can be
automatically done, GNU Guix.
live-bootstrap's overarching problem statement is;
While the primary author of this project does not believe Guix is a bad
project, the great reliance on Guile, the complexity of many of the
scripts and the rather steep learning curve to install and run Guix make
it a very non plug-and-play solution. Furthermore, there is currently
(Jan 2021) no possible way to run the bootstrap from outside of a
pre-existing Linux environment. Additionally, Guix uses many scripts and
distributed files that cannot be considered source code.
> How can a usable Linux system be created with only human-auditable, and
wherever possible, human-written, source code?
(NOTE: Guix is working on a Full Source Bootstrap, but Im not
completely sure what that entails).
Clarifications:
Furthermore, having an alternative bootstrap automation tool allows
people to have greater trust in the bootstrap procedure.
* "usable" means a modern toolchain, with appropriate utilities, that can be
used to expand the amount of software on the system, interactively, or
non-interactively.
* "human-auditable" is discretionary, but is usually fairly strict. See
"Specific things to be bootstrapped" below.
Comparison between GNU Guix and live-bootstrap
----------------------------------------------
Why is this difficult?
======================
+----------------------+----------------------+----------------------+
| Item | Guix | live-bootstrap |
+======================+======================+======================+
| Total size of seeds | ~30MB (Reduced | ~1KB |
| [1] | Source Bootstrap) | |
| | [2] | |
+----------------------+----------------------+----------------------+
| Use of kernel | Linux-Libre Kernel | Any Linux Kernel |
| | | (2.6+) [3] |
+----------------------+----------------------+----------------------+
| Implementation | Yes | No (in development) |
| complete | | |
+----------------------+----------------------+----------------------+
| Automation | Almost fully | Optional user |
| | automatic | customization |
+----------------------+----------------------+----------------------+
The core of a modern Linux system is primarily written in C and C++. C and C++
are **self-hosting**, ie, nearly every single C compiler is written in C.
[1]: Both projects only use software licensed under a FSF-approved
free software license. Kernel is excluded from seed.
[2]: Reiterating that Guix is working on a full source bootstrap,
although that still uses guile (~12 MB). [3]: Work is ongoing to use
other, smaller POSIX kernels.
Every single version of GCC was written in C. To avoid using an existing
toolchain, we need some way to be able to compile a GCC version without C. We
can use a less well-featured compiler, TCC, to do this. And so forth, until we
get to a fairly primitive C compiler written in assembly, ``cc_x86``.
Why would I want bootstrapping?
-------------------------------
Going up through this process requires a bunch of other utilities as well; the
autotools suite, guile and autogen, etc. These also have to be matched
appropriately to the toolchain available.
Why should I care?
------------------
That is outside of the scope of this README. Heres a few things you can
look at:
@ -117,7 +113,7 @@ bootstrapping. However, there are a number of non-auditable files used
in many of their packages. Here is a list of file types that we deem
unsuitable for bootstrapping.
1. Binaries (apart from seed hex0, kaem, kernel).
1. Binaries (apart from seed hex0, kaem, builder-hex0).
2. Any pre-generated configure scripts, or Makefile.ins from autotools.
3. Pre-generated bison/flex parsers (identifiable through a ``.y``
file).
@ -131,56 +127,18 @@ How does this work?
**For a more in-depth discussion, see parts.rst.**
sysa
~~~~
Firstly, ``builder-hex0`` is launched. ``builder-hex0`` is a minimal kernel that is
written in ``hex0``, existing in 3 self-bootstrapping stages.
sysa is the first system used in live-bootstrap. We move to a new
system after a reboot, which often occurs after the movement to a new
kernel. It is run by the seed Linux kernel provided by the user. It
compiles everything we need to be able to compile our own Linux kernel.
It runs fully in an initramfs and does not rely on disk support in the
seed Linux kernel.
This is capable of executing the entirety of ``stage0-posix``, (see
``seed/stage0-posix``), which produces a variety of useful utilities and a basic
C language, ``M2-Planet``.
sysb
~~~~
``stage0-posix`` runs a file called ``after.kaem``. This is a shell script that
builds and runs a small program called ``script-generator``. This program reads
``steps/manifest`` and converts it into a series of shell scripts that can be
executed in sequence to complete the bootstrap.
sysb is the second 'system' of live-bootstrap. This uses the Linux 4.9.10
kernel compiled within sysa. As we do not rely on disk support in sysa, we
need this intermediate system to be able to add the missing binaries to sysc
before moving into it. This is executed through kexec from sysa. At this point,
a SATA disk IS required.
sysc
~~~~
sysc is the (current) last 'system' of live-bootstrap. This is a continuation
from sysb, executed through util-linux's ``switch_root`` command which moves
the entire rootfs without a reboot. Every package from here on out is compiled
under this system, taking binaries from sysa. Chroot and bubblewrap modes skip
sysb, as it is obviously irrelevant to them.
Python-less build
-----------------
Python is no longer a requirement to set up the build system. The
repository is almost completely in a form where it can be used as the
source of a build.
1. Download required tarballs into ``sysa/distfiles`` and ``sysc/distfiles``.
You can use the ``download-distfiles.sh`` script.
2. Copy sysa/stage0-posix/src/* to the root of the repository.
3. Copy sysa/stage0-posix/src/bootstrap-seeds/POSIX/x86/kaem-optional-seed
to init in the root of the repository.
4. Copy sysa/after.kaem to after.kaem
5. Create a CPIO archive (eg, ``cpio --format newc --create --directory . > ../initramfs``).
6. Boot your initramfs and kernel.
chroot builds
~~~~~~~~~~~~~
For chroot based bootstraps you can skip creation of initramfs and instead start bootstrap with
``sudo chroot . bootstrap-seeds/POSIX/x86/kaem-optional-seed``
It is also recommended to copy everything to a new directory as bootstrapping messes up with files
in git repository and cannot be re-run again.
From this point forward, ``steps/manifest`` is effectively self documenting.
Each package built exists in ``steps/<pkg>``, and the build scripts can be seen
there.

View File

@ -20,27 +20,18 @@ download_source() {
echo "${checksum} ${dest_path}" | sha256sum -c
}
download_for_sys() {
local sysdir="${1}"
local distfiles="${sysdir}/distfiles"
mkdir -p "${distfiles}"
local entry
for entry in "${sysdir}"/*; do
[ -e "${entry}/sources" ] || continue
local line
# shellcheck disable=SC2162
while read line; do
# This is intentional - we want to split out ${line} into separate arguments.
# shellcheck disable=SC2086
download_source "${distfiles}" ${line}
done < "${entry}/sources"
done
}
set -e
cd "$(dirname "$(readlink -f "$0")")"
download_for_sys sysa
download_for_sys sysc
mkdir -p distfiles
for entry in steps/*; do
[ -e "${entry}/sources" ] || continue
# shellcheck disable=SC2162
while read line; do
# This is intentional - we want to split out ${line} into separate arguments.
# shellcheck disable=SC2086
download_source distfiles ${line}
done < "${entry}/sources"
done

338
lib/generator.py Executable file
View File

@ -0,0 +1,338 @@
#!/usr/bin/env python3
"""
This file contains all code required to generate the boot image for live-bootstrap
"""
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022-2023 Dor Askayo <dor.askayo@gmail.com>
# SPDX-FileCopyrightText: 2021 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2021 Melg Eight <public.melg8@gmail.com>
# SPDX-FileCopyrightText: 2021-23 fosslinux <fosslinux@aussies.space>
import hashlib
import os
import shutil
import tarfile
import requests
class Generator():
"""
Class responsible for generating the basic media to be consumed.
"""
git_dir = os.path.join(os.path.dirname(os.path.join(__file__)), '..')
distfiles_dir = os.path.join(git_dir, 'distfiles')
# pylint: disable=too-many-arguments
def __init__(self, tmpdir, arch, external_sources,
early_preseed, repo_path):
self.arch = arch
self.early_preseed = early_preseed
self.external_sources = external_sources
self.repo_path = repo_path
self.tmpdir = tmpdir
self.tmp_dir = tmpdir.path
self.external_dir = os.path.join(self.tmp_dir, 'external')
def prepare(self, using_kernel=False, kernel_bootstrap=False):
"""
Prepare basic media of live-bootstrap.
/steps -- contains steps to be built
/ -- contains seed to allow steps to be built, containing custom
scripts and stage0-posix
"""
# We use ext3 here; ext4 actually has a variety of extensions that
# have been added with varying levels of recency
# Linux 4.9.10 does not support a bunch of them
# Attempting to disable extensions that a particular e2fsprogs
# is *unaware* of causes the filesystem creation to fail
# We could hypothetically detect e2fsprogs version and create an
# argument matrix ... or we could just use ext3 instead which
# is effectively universally the same
if kernel_bootstrap:
init_path = os.path.join(self.tmp_dir, 'init')
os.mkdir(init_path)
self.tmp_dir = init_path
if self.repo_path or self.external_sources:
self.tmpdir.add_disk("external", filesystem="ext3")
self.tmpdir.mount_disk("external", "external")
else:
self.tmpdir.add_disk("external", tabletype="none")
elif using_kernel:
self.tmp_dir = os.path.join(self.tmp_dir, 'disk')
self.tmpdir.add_disk("disk", filesystem="ext3")
self.tmpdir.mount_disk("disk", "disk")
self.external_dir = os.path.join(self.tmp_dir, 'external')
os.makedirs(self.external_dir, exist_ok=True)
if self.early_preseed:
# Extract tar containing preseed
with tarfile.open(self.early_preseed, "r") as seed:
seed.extractall(self.tmp_dir)
shutil.copy2(os.path.join(self.git_dir, 'seed', 'preseeded.kaem'),
os.path.join(self.tmp_dir, 'kaem.x86'))
else:
self.stage0_posix()
self.seed()
self.steps()
self.distfiles()
self.create_fiwix_file_list()
if self.repo_path:
repo_dir = os.path.join(self.external_dir, 'repo-preseeded')
shutil.copytree(self.repo_path, repo_dir)
if kernel_bootstrap:
self.create_builder_hex0_disk_image(os.path.join(self.tmp_dir, 'disk.img'))
if kernel_bootstrap and (self.external_sources or self.repo_path):
self.tmpdir.umount_disk('external')
elif using_kernel:
self.tmpdir.umount_disk('disk')
def steps(self):
"""Copy in steps."""
source_manifest = self.get_source_manifest()
self.get_packages(source_manifest)
shutil.copytree(os.path.join(self.git_dir, 'steps'), os.path.join(self.tmp_dir, 'steps'))
def stage0_posix(self):
"""Copy in all of the stage0-posix"""
stage0_posix_base_dir = os.path.join(self.git_dir, 'seed', 'stage0-posix')
for f in os.listdir(stage0_posix_base_dir):
orig = os.path.join(stage0_posix_base_dir, f)
to = os.path.join(self.tmp_dir, f)
if os.path.isfile(orig):
shutil.copy2(orig, to)
else:
shutil.copytree(orig, to)
arch = stage0_arch_map.get(self.arch, self.arch)
kaem_optional_seed = os.path.join(self.git_dir, 'seed', 'stage0-posix', 'bootstrap-seeds',
'POSIX', arch, 'kaem-optional-seed')
shutil.copy2(kaem_optional_seed, os.path.join(self.tmp_dir, 'init'))
def seed(self):
"""Copy in extra seed files"""
seed_dir = os.path.join(self.git_dir, 'seed')
for f in os.listdir(seed_dir):
if os.path.isfile(os.path.join(seed_dir, f)):
shutil.copy2(os.path.join(seed_dir, f), os.path.join(self.tmp_dir, f))
def add_fiwix_files(self, file_list_path, dirpath):
"""Add files to the list to populate Fiwix file system"""
for root, _, filepaths in os.walk(dirpath):
if 'stage0-posix' in root:
continue
with open(file_list_path, 'a', encoding="utf-8") as file_list:
for filepath in filepaths:
file_list.write(f"/{os.path.join(root, filepath)}\n")
def create_fiwix_file_list(self):
"""Create a list of files to populate Fiwix file system"""
file_list_path = os.path.join(self.tmp_dir, 'steps', 'lwext4-1.0.0-lb1',
'files', 'fiwix-file-list.txt')
shutil.copyfile(os.path.join(self.tmp_dir, 'steps', 'lwext4-1.0.0-lb1',
'files', 'early-artifacts-needed-after-fiwix.txt'),
file_list_path)
save_cwd = os.getcwd()
os.chdir(self.tmp_dir)
self.add_fiwix_files(file_list_path, 'steps')
self.add_fiwix_files(file_list_path, 'distfiles')
os.chdir(save_cwd)
def distfiles(self):
"""Copy in distfiles"""
def copy_no_network_distfiles(out):
# Note that no network == no disk for kernel bootstrap mode
pre_src_path = os.path.join(self.git_dir, 'steps', 'pre-network-sources')
with open(pre_src_path, 'r', encoding="utf-8") as source_list:
for file in source_list.readlines():
file = file.strip()
shutil.copy2(os.path.join(self.distfiles_dir, file),
os.path.join(out, file))
early_distfile_dir = os.path.join(self.tmp_dir, 'external', 'distfiles')
main_distfile_dir = os.path.join(self.external_dir, 'distfiles')
if early_distfile_dir != main_distfile_dir:
os.makedirs(early_distfile_dir)
copy_no_network_distfiles(early_distfile_dir)
if self.external_sources:
os.mkdir(main_distfile_dir)
shutil.copytree(self.distfiles_dir, main_distfile_dir)
else:
os.mkdir(main_distfile_dir)
copy_no_network_distfiles(main_distfile_dir)
@staticmethod
def output_dir(srcfs_file, dirpath):
"""Add a directory to srcfs file system"""
srcline = f"src 0 {dirpath}\n"
srcfs_file.write(srcline.encode())
@staticmethod
def output_file(srcfs_file, filepath):
"""Add a file to srcfs file system"""
srcline = f"src {os.path.getsize(filepath)} {filepath}\n"
srcfs_file.write(srcline.encode())
with open(filepath, 'rb') as srcfile:
srcfs_file.write(srcfile.read())
def output_tree(self, srcfs_file, treepath):
"""Add a tree of files to srcfs file system"""
self.output_dir(srcfs_file, treepath)
for root, dirs, files in os.walk(treepath):
if ".git" in root:
continue
for dirpath in dirs:
if ".git" in dirpath:
continue
self.output_dir(srcfs_file, os.path.join(root, dirpath))
for filepath in files:
if ".git" in filepath:
continue
self.output_file(srcfs_file, os.path.join(root, filepath))
def append_srcfs(self, image_file):
"""Append srcfs file system to disk image"""
save_cwd = os.getcwd()
os.chdir(self.tmp_dir)
self.output_tree(image_file, '.')
# Add commands to kick off stage0-posix
cmd = ' '.join(['hex0',
'./bootstrap-seeds/POSIX/x86/hex0_x86.hex0',
'./bootstrap-seeds/POSIX/x86/hex0-seed\n'])
image_file.write(cmd.encode())
cmd = ' '.join(['hex0',
'./bootstrap-seeds/POSIX/x86/kaem-minimal.hex0',
'./bootstrap-seeds/POSIX/x86/kaem-optional-seed\n'])
image_file.write(cmd.encode())
cmd = ' '.join(['./bootstrap-seeds/POSIX/x86/kaem-optional-seed', './kaem.x86\n'])
image_file.write(cmd.encode())
os.chdir(save_cwd)
def create_builder_hex0_disk_image(self, image_file_name):
"""Create builder-hex0 disk image"""
shutil.copyfile(os.path.join('seed', 'stage0-posix', 'bootstrap-seeds',
'NATIVE', 'x86', 'builder-hex0-x86-stage1.img'),
image_file_name)
with open(image_file_name, 'ab') as image_file:
# Append stage2 hex0 source
with open(os.path.join('kernel-bootstrap', 'builder-hex0-x86-stage2.hex0'),
encoding="utf-8") as infile:
image_file.write(infile.read().encode())
# Pad to next sector
current_size = os.stat(image_file_name).st_size
while current_size % 512 != 0:
image_file.write(b'\0')
current_size += 1
self.append_srcfs(image_file)
current_size = os.stat(image_file_name).st_size
megabyte = 1024 * 1024
# fill file with zeros up to next megabyte
extra = current_size % megabyte
round_up = megabyte - extra
with open(image_file_name, 'ab') as image_file:
image_file.write(b'\0' * round_up)
current_size += round_up
# fill file with zeros up to desired size, one megabyte at a time
with open(image_file_name, 'ab') as image_file:
while current_size < 16384 * megabyte:
image_file.write(b'\0' * megabyte)
current_size += megabyte
def check_file(self, file_name, expected_hash):
"""Check hash of downloaded source file."""
with open(file_name, "rb") as downloaded_file:
downloaded_content = downloaded_file.read() # read entire file as bytes
readable_hash = hashlib.sha256(downloaded_content).hexdigest()
if expected_hash == readable_hash:
return
raise ValueError(f"Checksum mismatch for file {os.path.basename(file_name)}:\n\
expected: {expected_hash}\n\
actual: {readable_hash}\n\
When in doubt, try deleting the file in question -- it will be downloaded again when running \
this script the next time")
def download_file(self, url, directory, file_name):
"""
Download a single source archive.
"""
abs_file_name = os.path.join(directory, file_name)
# Create a directory for downloaded file
if not os.path.isdir(directory):
os.mkdir(directory)
# Actually download the file
headers = {
"Accept-Encoding": "identity"
}
if not os.path.isfile(abs_file_name):
print(f"Downloading: {file_name}")
response = requests.get(url, allow_redirects=True, stream=True,
headers=headers, timeout=20)
if response.status_code == 200:
with open(abs_file_name, 'wb') as target_file:
target_file.write(response.raw.read())
else:
raise requests.HTTPError("Download failed.")
return abs_file_name
def get_packages(self, source_manifest):
"""Prepare remaining sources"""
for line in source_manifest.split("\n"):
line = line.strip().split(" ")
path = self.download_file(line[2], line[1], line[3])
self.check_file(path, line[0])
@classmethod
def get_source_manifest(cls):
"""
Generate a source manifest for the system.
"""
manifest_lines = []
directory = os.path.relpath(cls.distfiles_dir, cls.git_dir)
# Find all source files
steps_dir = os.path.join(cls.git_dir, 'steps')
for file in os.listdir(steps_dir):
if os.path.isdir(os.path.join(steps_dir, file)):
sourcef = os.path.join(steps_dir, file, "sources")
if os.path.exists(sourcef):
# Read sources from the source file
with open(sourcef, "r", encoding="utf_8") as sources:
for line in sources.readlines():
line = line.strip().split(" ")
if len(line) > 2:
file_name = line[2]
else:
# Automatically determine file name based on URL.
file_name = os.path.basename(line[0])
manifest_lines.append(f"{line[1]} {directory} {line[0]} {file_name}")
return "\n".join(manifest_lines)
stage0_arch_map = {
"amd64": "AMD64",
}

View File

@ -1,132 +0,0 @@
#!/usr/bin/env python3
"""
This file contains a few functions to be shared by all Sys* classes
"""
# SPDX-FileCopyrightText: 2022-2023 Dor Askayo <dor.askayo@gmail.com>
# SPDX-FileCopyrightText: 2021-23 fosslinux <fosslinux@aussies.space>
# SPDX-FileCopyrightText: 2021 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import hashlib
import glob
import subprocess
import requests
class SysGeneral:
"""
A class from which all Sys* class are extended.
Contains functions used in all Sys*
"""
# All of these are variables defined in the individual Sys* classes
cache_dir = None
base_dir = None
git_dir = None
sys_dir = None
initramfs_path = None
tmp_dir = None
def check_file(self, file_name, expected_hash):
"""Check hash of downloaded source file."""
with open(file_name, "rb") as downloaded_file:
downloaded_content = downloaded_file.read() # read entire file as bytes
readable_hash = hashlib.sha256(downloaded_content).hexdigest()
if expected_hash == readable_hash:
return
raise ValueError(f"Checksum mismatch for file {os.path.basename(file_name)}:\n\
expected: {expected_hash}\n\
actual: {readable_hash}\n\
When in doubt, try deleting the file in question -- it will be downloaded again when running \
this script the next time")
def download_file(self, url, directory, file_name):
"""
Download a single source archive.
"""
abs_file_name = os.path.join(directory, file_name)
# Create a directory for downloaded file
if not os.path.isdir(directory):
os.mkdir(directory)
# Actually download the file
headers = {
"Accept-Encoding": "identity"
}
if not os.path.isfile(abs_file_name):
print(f"Downloading: {file_name}")
response = requests.get(url, allow_redirects=True, stream=True,
headers=headers, timeout=20)
if response.status_code == 200:
with open(abs_file_name, 'wb') as target_file:
target_file.write(response.raw.read())
else:
raise requests.HTTPError("Download failed.")
return abs_file_name
def get_packages(self, source_manifest):
"""Prepare remaining sources"""
for line in source_manifest.split("\n"):
line = line.strip().split(" ")
path = self.download_file(line[2], line[1], line[3])
self.check_file(path, line[0])
@classmethod
def get_source_manifest(cls):
"""
Generate a source manifest for the system.
"""
manifest_lines = []
directory = os.path.relpath(cls.cache_dir, cls.git_dir)
# Find all source files
for file in os.listdir(cls.sys_dir):
if os.path.isdir(os.path.join(cls.sys_dir, file)):
sourcef = os.path.join(cls.sys_dir, file, "sources")
if os.path.exists(sourcef):
# Read sources from the source file
with open(sourcef, "r", encoding="utf_8") as sources:
for line in sources.readlines():
line = line.strip().split(" ")
if len(line) > 2:
file_name = line[2]
else:
# Automatically determine file name based on URL.
file_name = os.path.basename(line[0])
manifest_lines.append(f"{line[1]} {directory} {line[0]} {file_name}")
return "\n".join(manifest_lines)
def make_initramfs(self):
"""Package binary bootstrap seeds and sources into initramfs."""
self.initramfs_path = os.path.join(self.tmp_dir, 'initramfs')
# Create a list of files to go within the initramfs
file_list = glob.glob(os.path.join(self.tmp_dir, '**'), recursive=True)
# Use built-in removeprefix once we can use Python 3.9
def remove_prefix(text, prefix):
if text.startswith(prefix):
return text[len(prefix):]
return text # or whatever
file_list = [remove_prefix(f, self.tmp_dir + os.sep) for f in file_list]
# Create the initramfs
with open(self.initramfs_path, "w", encoding="utf_8") as initramfs:
# pylint: disable=consider-using-with
cpio = subprocess.Popen(
["cpio", "--format", "newc", "--create",
"--directory", self.tmp_dir],
stdin=subprocess.PIPE, stdout=initramfs)
cpio.communicate(input='\n'.join(file_list).encode())
stage0_arch_map = {
"amd64": "AMD64",
}

View File

@ -24,7 +24,6 @@ class Tmpdir:
Represents a tmpdir
"""
_syses = {}
_disks = {}
_disk_filesystems = {}
_mountpoints = {}
@ -60,19 +59,11 @@ class Tmpdir:
mount("tmpfs", self.path, "tmpfs", f"size={size}")
self._type = TmpType.TMPFS
def add_sys(self, name, subdir=None):
"""Create a subdirectory and register a sys"""
if subdir is None:
subdir = name
sys_path = os.path.join(self.path, name)
if not os.path.exists(sys_path):
os.mkdir(sys_path)
return sys_path
def add_disk(self, name, size="16G", filesystem="ext4"):
# pylint: disable=too-many-arguments
def add_disk(self, name, size="16G", filesystem="ext4", tabletype="msdos", mkfs_args=None):
"""Add a disk"""
disk_path = os.path.join(self.path, f"{name}.img")
self._disks[name] = create_disk(disk_path, "msdos", filesystem, size)
self._disks[name] = create_disk(disk_path, tabletype, filesystem, size, mkfs_args=mkfs_args)
self._disk_filesystems[name] = filesystem
# Allow executing user to access it
run_as_root("chown", getpass.getuser(), self._disks[name])

View File

@ -31,8 +31,10 @@ def run_as_root(*args, **kwargs):
return run("sudo", *args, **kwargs)
return run(*args, **kwargs)
def create_disk(image, disk_type, fs_type, size):
def create_disk(image, disk_type, fs_type, size, mkfs_args=None):
"""Create a disk image, with a filesystem on it"""
if mkfs_args is None:
mkfs_args = []
run('truncate', '-s', size, image)
# First find the device we will use, then actually use it
loop_dev = run_as_root('losetup', '-f', capture_output=True).stdout.decode().strip()
@ -40,9 +42,9 @@ def create_disk(image, disk_type, fs_type, size):
# Create the partition
if disk_type != "none":
run_as_root('parted', '--script', image, 'mklabel', disk_type, 'mkpart',
'primary', 'ext4', '0%', '100%')
'primary', fs_type, '0%', '100%')
run_as_root('partprobe', loop_dev)
run_as_root('mkfs.' + fs_type, loop_dev + "p1")
run_as_root('mkfs.' + fs_type, loop_dev + "p1", *mkfs_args)
return loop_dev
def mount(source, target, fs_type, options='', **kwargs):

147
parts.rst
View File

@ -155,14 +155,46 @@ checksumming tool, that we use to ensure reproducibility and authenticity
of generated binaries. We also build initial ``untar``, ``ungz`` and ``unbz2``
utilities to deal with compressed archives.
``/sysa``
=========
live-bootstrap seed
===================
We now move into the ``/sysa`` directory. As stage0-posix has no
concept of ``chdir()`` (not added until very late in stage0-posix),
we have to copy a lot of files into the root of the initramfs, making it
very messy. We get into the move ordered directory ``/sysa`` here,
copying over all of the required binaries from ``/``.
``stage0-posix`` executes a file ``after.kaem``, which creates a kaem script to
continue the bootstrap. This is responsible for cleaning up the mess in
``/x86/bin`` and moving it to the permanent ``/usr/bin``, and setting a few
environment variables.
script-generator
================
``script-generator`` is a program that translates live-bootstrap's
domain-specific manifest language into shell scripts that can be run to complete
the bootstrap. The translator is implemented in ``M2-Planet``.
The language is fairly simple; each line has the format
``<directive>: <arguments> <predicate>``. A predicate only runs the line if a
particular condition is true.
The following directives are supported:
* ``build``, builds a particular package defined in ``steps/``.
* ``improve``, runs a script making a distinct and logical improvement to the
live bootstrap system.
* ``define``, define a variable evaluated from other constants/variables.
* ``jump``, moves into a new rootfs/kernel using a custom script.
checksum-transcriber 1.0
========================
``checksum-transcriber`` is a small program that converts live-bootstrap's
source specification for packages into a SHA256SUM file that can be used to
checksum source tarballs.
simple-patch 1.0
================
``simple-patch`` is a rudimentary patching program. It works by matching for a
text block given to it, and replacing it with another text block. This is
sufficient for the early patching required before we have full proper GNU patch.
mes 0.25
========
@ -177,6 +209,10 @@ to this part:
2. We then use this to recompile the Mes interpreter as well as building
the libc. This second interpreter is faster and less buggy.
From this point until musl, we are capable of making non-standard and strange
libraries. All libraries are in ``/usr/lib/mes``, and includes are in
``/usr/include/mes``, as they are incompatible with musl.
tinycc 0.9.26
=============
@ -215,8 +251,8 @@ This is a Linux 2.0 clone which is much simpler to understand and build than
Linux. This version of Fiwix is a fork of 1.4.0 that contains many
modifications and enhancements to support live-boostrap.
lwext4 1.0.0
============
lwext4 1.0.0-lb1
================
If the kernel bootstrap option is enabled then `lwext4 <https://github.com/gkostka/lwext4>`
is built next. This is a library for creating ext2/3/4 file systems from user land.
@ -230,11 +266,19 @@ kexec-fiwix
If the kernel bootstrap option is enabled then a C program `kexec-fiwix` is compiled
and run which places the Fiwix ram drive in memory and launches the Fiwix kernel.
kexec-linux
===========
esfu 1.0
========
If the kernel bootstrap option is enabled then a C program `kexec-linux` is compiled.
This is used as part of the go_sysb step later to launch the Linux kernel.
This is an extremely crippled basic implementation of ``mount`` and ``mknod``.
Sufficient only for the next step.
early_mount_disk
================
When using kernel bootstrap, distfiles from this point exist on an external
disk. Using ``esfu``'s ``mount`` and ``mknod``, we are able to mount this disk.
This is unnecessary when not using kernel bootstrap as everything is done on the
disk.
make 3.82
=========
@ -304,6 +348,12 @@ Bash ships with a bison pre-generated file here which we delete.
Unfortunately, we have not bootstrapped bison but fortunately for us,
heirloom yacc is able to cope here.
update_env
==========
This is a simple script that makes some small updates to the env file that were
not possible when using kaem.
flex 2.5.11
===========
@ -321,8 +371,8 @@ tcc 0.9.27 (patched)
We recompile ``tcc`` with some patches needed to build musl.
musl 1.1.24
===========
musl 1.1.24 and musl_libdir
===========================
``musl`` is a C standard library that is lightweight, fast, simple,
free, and strives to be correct in the sense of standards-conformance
@ -335,6 +385,9 @@ apply a few patches. In particular, we replace all weak symbols with
strong symbols and will patch ``tcc`` in the next step to ignore
duplicate symbols.
We do not use any of ``/usr/lib/mes`` or ``/usr/include/mes`` any longer, rather
using ``/usr/lib`` and ``/usr/include`` like normal.
tcc 0.9.27 (musl)
=================
@ -586,12 +639,6 @@ libtool 2.2.4
GNU Libtool is the final part of GNU Autotools. It is a script used to hide away differences
when compiling shared libraries on different platforms.
bash 2.05b
==========
Up to this point, our build of ``bash`` could run scripts but could not be used
interactively. Rebuilding bash makes this functionality work.
automake 1.15.1
===============
@ -646,6 +693,12 @@ GCC can build the latest as of the time of writing musl version.
We also don't need any of the TCC patches that we used before.
To accomodate Fiwix, there are patches to avoid syscalls set_thread_area and clone.
Linux headers 5.10.41
=====================
This gets some headers out of the Linux kernel that are required to use the
kernel ABI, needed for ``util-linux``.
gcc 4.0.4
=========
@ -655,10 +708,15 @@ util-linux 2.19.1
=================
``util-linux`` contains a number of general system administration utilities.
Most pressingly, we need these for being able to mount disks (for non-chroot
mode, but it is built it in chroot mode anyway because it will likely be useful
later). The latest version is not used because of autotools/GCC
incompatibilities.
This gives us access to a much less crippled version of ``mount`` and ``mknod``.
The latest version is not used because of autotools/GCC incompatibilities.
move_disk
=========
In ``kernel-bootstrap`` mode, we have been working off an initramfs for some
things up until now. At this point we are now capable of moving to it entirely,
so we do so.
kbd-1.15
========
@ -685,6 +743,12 @@ bc 1.07.1
``bc`` is a console based calculator that is sometime used in scripts. We need ``bc``
to rebuild some Linux kernel headers.
kexec-linux
===========
If the kernel bootstrap option is enabled then a C program ``kexec-linux`` is compiled.
This can be used to launch a Linux kernel from Fiwix.
kexec-tools 2.0.22
==================
@ -693,13 +757,6 @@ Linux kernel without a manual restart from within a running system. It is a
kind of soft-restart. It is only built for non-chroot mode, as we only use it
in non-chroot mode. It is used to go into sysb/sysc.
create_sysb
===========
The next step is not a package, but the creation of the sysb rootfs, containing
all of the scripts for sysb (which merely move to sysc). Again, this is only
done in non-chroot mode, because sysb does not exist in chroot mode.
Linux kernel 4.9.10
===================
@ -716,30 +773,10 @@ so we use a ``find`` command to remove those, which are automatically regenerate
The kernel config was originally taken from Void Linux, and was then modified
for the requirements of live-bootstrap, including compiler features, drivers,
and removing modules. Modules are unused. They are difficult to transfer to
subsequent systems, and we do not have ``modprobe``. Lastly,
the initramfs of sysb is generated in this stage, using ``gen_init_cpio`` within
the Linux kernel tree. This avoids the compilation of ``cpio`` as well.
subsequent systems, and we do not have ``modprobe``.
musl 1.2.4
==========
Prior to booting Linux, musl is rebuilt yet again with syscalls
``clone`` and ``set_thread_area`` enabled for Linux thread support.
go_sysb
=======
This is the last step of sysa, run for non-chroot mode. It uses kexec to load
the new Linux kernel into RAM and execute it, moving into sysb.
In chroot, sysb is skipped, and data is transferred directly to sysc and
chrooted into.
sysb
====
sysb is purely a transition to sysc, allowing binaries from sysa to get onto a
disk (as sysa does not necessarily have hard disk support in the kernel).
It populates device nodes, mounts sysc, copies over data, and executes sysc.
We then kexec to use the new Linux kernel, using ``kexec-tools`` for a Linux
kernel and ``kexec-linux`` for Fiwix.
curl 7.88.1
===========

View File

@ -17,18 +17,16 @@ import argparse
import os
import shutil
from sysa import SysA
from sysc import SysC
from lib.utils import run, run_as_root
from lib.sysgeneral import stage0_arch_map
from lib.tmpdir import Tmpdir
from lib.generator import Generator, stage0_arch_map
def create_configuration_file(args):
"""
Creates bootstrap.cfg file which would contain options used to
customize bootstrap.
"""
config_path = os.path.join('sysa', 'bootstrap.cfg')
config_path = os.path.join('steps', 'bootstrap.cfg')
with open(config_path, "w", encoding="utf_8") as config:
config.write(f"FORCE_TIMESTAMPS={args.force_timestamps}\n")
config.write(f"CHROOT={args.chroot or args.bwrap}\n")
@ -38,7 +36,10 @@ def create_configuration_file(args):
config.write(f"INTERNAL_CI={args.internal_ci}\n")
config.write(f"BARE_METAL={args.bare_metal}\n")
if (args.bare_metal or args.qemu) and not args.kernel:
config.write("DISK=sda\n")
if args.repo or args.external_sources:
config.write("DISK=sdb1\n")
else:
config.write("DISK=sdb\n")
config.write("KERNEL_BOOTSTRAP=True\n")
else:
config.write("DISK=sda1\n")
@ -49,7 +50,7 @@ def create_configuration_file(args):
def main():
"""
A few command line arguments to customize bootstrap.
This function also creates SysA object which prepares directory
This function also creates object which prepares directory
structure with bootstrap seeds and all sources.
"""
parser = argparse.ArgumentParser()
@ -151,16 +152,15 @@ def main():
if args.tmpfs:
tmpdir.tmpfs(size=args.tmpfs_size)
# sys
system_c = SysC(arch=args.arch, tmpdir=tmpdir,
external_sources=args.external_sources)
system_a = SysA(arch=args.arch, early_preseed=args.early_preseed,
tmpdir=tmpdir, external_sources=args.external_sources,
repo_path=args.repo)
generator = Generator(tmpdir=tmpdir,
arch=args.arch,
external_sources=args.external_sources,
repo_path=args.repo,
early_preseed=args.early_preseed)
bootstrap(args, system_a, system_c, tmpdir)
bootstrap(args, generator, tmpdir)
def bootstrap(args, system_a, system_c, tmpdir):
def bootstrap(args, generator, tmpdir):
"""Kick off bootstrap process."""
print(f"Bootstrapping {args.arch} -- SysA")
if args.chroot:
@ -171,17 +171,15 @@ print(shutil.which('chroot'))
chroot_binary = run_as_root('python3', '-c', find_chroot,
capture_output=True).stdout.decode().strip()
system_c.prepare(create_disk_image=False)
system_a.prepare(create_initramfs=False)
generator.prepare(using_kernel=False)
arch = stage0_arch_map.get(args.arch, args.arch)
init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed')
run_as_root('env', '-i', 'PATH=/bin', chroot_binary, system_a.tmp_dir, init)
run_as_root('env', '-i', 'PATH=/bin', chroot_binary, generator.tmp_dir, init)
elif args.bwrap:
if not args.internal_ci or args.internal_ci == "pass1":
system_c.prepare(create_disk_image=False)
system_a.prepare(create_initramfs=False)
generator.prepare(using_kernel=False)
arch = stage0_arch_map.get(args.arch, args.arch)
init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed')
@ -191,7 +189,7 @@ print(shutil.which('chroot'))
'--unshare-net',
'--clearenv',
'--setenv', 'PATH', '/usr/bin',
'--bind', system_a.tmp_dir, '/',
'--bind', generator.tmp_dir, '/',
'--dir', '/dev',
'--dev-bind', '/dev/null', '/dev/null',
'--dev-bind', '/dev/zero', '/dev/zero',
@ -210,7 +208,7 @@ print(shutil.which('chroot'))
'--unshare-net' if args.external_sources else None,
'--clearenv',
'--setenv', 'PATH', '/usr/bin',
'--bind', system_a.tmp_dir + "/sysc_image", '/',
'--bind', generator.tmp_dir + "/sysc_image", '/',
'--dir', '/dev',
'--dev-bind', '/dev/null', '/dev/null',
'--dev-bind', '/dev/zero', '/dev/zero',
@ -226,40 +224,39 @@ print(shutil.which('chroot'))
elif args.bare_metal:
if args.kernel:
system_c.prepare(create_disk_image=True)
system_a.prepare(create_initramfs=True)
generator.prepare(using_kernel=True)
print("Please:")
print(" 1. Take tmp/sysa/initramfs and your kernel, boot using this.")
print(" 2. Take tmp/sysc/disk.img and put this on a writable storage medium.")
print(" 1. Take tmp/initramfs and your kernel, boot using this.")
print(" 2. Take tmp/disk.img and put this on a writable storage medium.")
else:
system_a.prepare(create_initramfs=True, kernel_bootstrap=True)
generator.prepare(kernel_bootstrap=True)
print("Please:")
print(" 1. Take tmp/sysa/sysa.img and write it to a boot drive and then boot it.")
print(" 1. Take tmp/disk.img and write it to a boot drive and then boot it.")
else:
if args.kernel:
system_c.prepare(create_disk_image=True)
system_a.prepare(create_initramfs=True)
generator.prepare(using_kernel=True)
run(args.qemu_cmd,
'-enable-kvm',
'-m', str(args.qemu_ram) + 'M',
'-smp', str(args.cores),
'-no-reboot',
'-hda', tmpdir.get_disk("sysc"),
'-drive', 'file=' + tmpdir.get_disk("disk") + ',format=raw',
'-drive', 'file=' + tmpdir.get_disk("external") + ',format=raw',
'-nic', 'user,ipv6=off,model=e1000',
'-kernel', args.kernel,
'-initrd', system_a.initramfs_path,
'-nographic',
'-append', 'console=ttyS0')
'-append', 'console=ttyS0 root=/dev/sda1 rootfstype=ext3 init=/init rw')
else:
system_a.prepare(create_initramfs=True, kernel_bootstrap=True)
generator.prepare(kernel_bootstrap=True)
run(args.qemu_cmd,
'-enable-kvm',
'-m', "4G",
'-smp', str(args.cores),
'-no-reboot',
'-drive', 'file=' + os.path.join(system_a.tmp_dir, 'sysa.img') + ',format=raw',
'-drive', 'file=' + os.path.join(generator.tmp_dir, 'disk.img') + ',format=raw',
'-drive', 'file=' + tmpdir.get_disk("external") + ',format=raw',
'-machine', 'kernel-irqchip=split',
'-nic', 'user,ipv6=off,model=e1000',
'-nographic')

View File

@ -9,17 +9,7 @@
set -ex
# Set commonly used variables
sysa=/sysa
DISTFILES=/sysa/distfiles
PREFIX=/usr
BINDIR=${PREFIX}/bin
LIBDIR=${PREFIX}/lib/mes
INCDIR=${PREFIX}/include/mes
SRCDIR=${PREFIX}/src
TMPDIR=/tmp # tmpdir is needed for patch to work
PATH=${BINDIR}
PATH=/${ARCH_DIR}/bin
cd ${sysa}
exec bash run.sh
catm seed-full.kaem /steps/env seed.kaem
kaem --file seed-full.kaem

8
seed/preseeded.kaem Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
#
# SPDX-FileCopyrightText: 2023 fosslinux <fosslinux@aussies.space>
#
# SPDX-License-Identifier: GPL-3.0-or-later
/script-generator /steps/manifest
/usr/bin/kaem --file /preseed-jump.kaem

627
seed/script-generator.c Normal file
View File

@ -0,0 +1,627 @@
/*
* SPDX-FileCopyrightText: 2023 fosslinux <fosslinux@aussies.space>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define MAX_TOKEN 64
#define MAX_STRING 2048
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bootstrappable.h>
struct Token {
char *val;
struct Token *next;
};
typedef struct Token Token;
#define TYPE_BUILD 1
#define TYPE_IMPROVE 2
#define TYPE_DEFINE 3
#define TYPE_JUMP 4
#define TYPE_MAINT 5
struct Directive {
Token *tok;
struct Directive *next;
int type;
char *arg; /* The primary argument */
};
typedef struct Directive Directive;
/* Tokenizer. */
/* Skip over a comment. */
char consume_comment(FILE *in) {
/* Discard the rest of the line. */
char c = fgetc(in);
while (c != -1 && c != '\n')
c = fgetc(in);
return c;
}
char consume_line(FILE *in, Directive *directive) {
char c = fgetc(in);
/* Short-circuit if whole line is comment or blank line. */
if (c == '#') {
c = consume_comment(in);
return c;
} else if (c == '\n' || c == -1) {
return c;
}
/* Ok, we will have something to put here. */
directive->next = calloc(1, sizeof(Directive));
directive = directive->next;
Token *head = calloc(1, sizeof(Token));
Token *cur = head;
char *out;
int i = 0;
while (c != -1 && c != '\n') {
/* Initialize next token. */
cur->next = calloc(1, sizeof(Token));
cur = cur->next;
cur->val = calloc(MAX_TOKEN, sizeof(char));
out = cur->val;
/* Copy line to token until a space (or EOL/EOF) or comment is found. */
while (c != -1 && c != '\n' && c != ' ' && c != '#') {
out[0] = c;
out += 1;
c = fgetc(in);
}
/* Go to start of next token. */
if (c == ' ') {
c = fgetc(in);
}
/* Handle comment. */
if (c == '#') {
c = consume_comment(in);
}
}
/* Add information to directive. */
directive->tok = head->next;
return c;
}
Directive *tokenizer(FILE *in) {
Directive *head = calloc(1, sizeof(Directive));
Directive *cur = head;
char c;
while (c != -1) {
/*
* Note that consume_line fills cur->next, not cur.
* This avoids having an empty last Directive.
*/
c = consume_line(in, cur);
if (cur->next != NULL) {
cur = cur->next;
}
}
return head->next;
}
/* Config variables. */
struct Variable {
char *name;
char *val;
struct Variable *next;
};
typedef struct Variable Variable;
Variable *variables;
Variable *load_config() {
FILE *config = fopen("/steps/bootstrap.cfg", "r");
/* File does not exist check. */
if (config == NULL) {
return NULL;
}
char *line = calloc(MAX_STRING, sizeof(char));
Variable *head = calloc(1, sizeof(Variable));
Variable *cur = head;
/* For each line... */
char *equals;
while (fgets(line, MAX_STRING, config) != 0) {
/* Weird M2-Planet behaviour. */
if (*line == 0) {
break;
}
cur->next = calloc(1, sizeof(Variable));
cur = cur->next;
/* Split on the equals. First half is name, second half is value. */
equals = strchr(line, '=');
if (equals == 0) {
fputs("bootstrap.cfg should have the format var=val on each line.", stderr);
exit(1);
}
cur->name = calloc(equals - line + 1, sizeof(char));
strncpy(cur->name, line, equals - line);
equals += 1;
cur->val = calloc(strlen(equals), sizeof(char));
strncpy(cur->val, equals, strlen(equals) - 1);
line = calloc(MAX_STRING, sizeof(char));
}
variables = head->next;
fclose(config);
}
void output_config(FILE *out) {
Variable *variable;
for (variable = variables; variable != NULL; variable = variable->next) {
fputs(variable->name, out);
fputs("=", out);
fputs(variable->val, out);
fputs("\n", out);
}
}
char *get_var(char *name) {
/* Search through existing variables. */
Variable *var;
Variable *last;
for (var = variables; var != NULL; var = var->next) {
if (strcmp(name, var->name) == 0) {
return var->val;
}
last = var;
}
/* If the variable is unset, prompt the user. */
if (variables == NULL) {
variables = calloc(1, sizeof(Variable));
var = variables;
} else {
last->next = calloc(1, sizeof(Variable));
var = last->next;
}
var->name = calloc(strlen(name) + 1, sizeof(char));
strcpy(var->name, name);
var->val = calloc(MAX_STRING, sizeof(char));
fputs("You have not set a value for ", stdout);
fputs(name, stdout);
fputs(" in bootstrap.cfg. Please set it now:\n", stdout);
while (fgets(var->val, MAX_STRING, stdin) == 0 || var->val[0] == '\n') {
fputs("Error inputting, try again:\n", stdout);
}
if (var->val[0] == 0) {
fputs("You put in an EOF!\n", stderr);
exit(1);
}
/* Trim the newline. */
var->val[strlen(var->val)] = 0;
return var->val;
}
/* Recursive descent interpreter. */
Token *fill(Token *tok, Directive *directive, int type) {
directive->type = type;
directive->arg = tok->val;
return tok->next;
}
Token *logic(Token *tok, char **val) {
/* logic = "("
* (name |
* (name "==" value) |
* (logic "||" logic) |
* (logic "&&" logic))
* ")"
*/
char *lhs = tok->val;
char *rhs;
tok = tok->next;
if (strcmp(tok->val, ")") == 0) {
/* Case where it's just a constant. */
*val = lhs;
return tok;
} else if (strcmp(tok->val, "==") == 0) {
/* Case for equality. */
rhs = tok->next->val;
tok = tok->next->next;
if (strcmp(get_var(lhs), rhs) == 0) {
lhs = "True";
} else {
lhs = "False";
}
} else {
fputs("Expected == after ", stderr);
fputs(lhs, stderr);
fputs(" in logic\n", stderr);
exit(1);
}
if (strcmp(tok->val, ")") == 0) {
*val = lhs;
return tok;
} else if (strcmp(tok->val, "||") == 0) {
/* OR */
tok = logic(tok->next, &rhs);
if (strcmp(lhs, "True") == 0 || strcmp(rhs, "True") == 0) {
lhs = "True";
} else {
lhs = "False";
}
} else if (strcmp(tok->val, "&&") == 0) {
/* AND */
tok = logic(tok->next, &rhs);
if (strcmp(lhs, "True") == 0 && strcmp(rhs, "True") == 0) {
lhs = "True";
} else {
lhs = "False";
}
} else {
fputs("Expected || or && in logic\n", stderr);
exit(1);
}
*val = lhs;
return tok;
}
Token *primary_logic(Token *tok, char **val) {
/* Starting ( */
if (strcmp(tok->val, "(") != 0) {
fputs("Expected logic to begin with (\n", stderr);
exit(1);
}
tok = tok->next;
tok = logic(tok, val);
if (strcmp(tok->val, ")") != 0) {
fputs("Expected logic to end with )\n", stderr);
exit(1);
}
return tok;
}
int eval_predicate(Token *tok) {
char *result;
tok = primary_logic(tok, &result);
return strcmp(result, "True") == 0;
}
Token *define(Token *tok, Directive *directive) {
/* define = name "=" (logic | constant) */
char *name = tok->val;
tok = tok->next;
if (strcmp(tok->val, "=") != 0) {
fputs("define of ", stderr);
fputs(name, stderr);
fputs(" has a missing equals\n", stderr);
exit(1);
}
tok = tok->next;
char *val = calloc(MAX_STRING, sizeof(char));
if (strcmp(tok->val, "(") == 0) {
/* It is a logic. */
tok = primary_logic(tok, &val);
} else {
/* It is a constant. */
strcpy(val, tok->val);
}
/* Check for predicate. */
tok = tok->next;
if (tok != NULL) {
if (!eval_predicate(tok)) {
/* Nothing more to do. */
return tok;
}
}
/* Update existing variable, or else, add to the end of variables. */
/* Special case: empty variables. */
if (variables == NULL) {
variables = calloc(1, sizeof(Variable));
variables->name = name;
variables->val = val;
}
Variable *var;
for (var = variables; var->next != NULL; var = var->next) {
if (strcmp(var->next->name, name) == 0) {
var->next->val = val;
break;
}
}
if (var->next == NULL) {
/* We did not update an existing variable. */
var->next = calloc(1, sizeof(Variable));
var->next->name = name;
var->next->val = val;
}
return tok;
}
int interpret(Directive *directive) {
/* directive = (build | improve | define | jump | maint) predicate? */
Token *tok = directive->tok;
if (strcmp(tok->val, "build:") == 0) {
tok = fill(tok->next, directive, TYPE_BUILD);
} else if (strcmp(tok->val, "improve:") == 0) {
tok = fill(tok->next, directive, TYPE_IMPROVE);
} else if (strcmp(tok->val, "jump:") == 0) {
tok = fill(tok->next, directive, TYPE_JUMP);
} else if (strcmp(tok->val, "maint:") == 0) {
tok = fill(tok->next, directive, TYPE_MAINT);
} else if (strcmp(tok->val, "define:") == 0) {
tok = define(tok->next, directive);
return 1; /* There is no codegen for a define. */
}
if (tok != NULL) {
return !eval_predicate(tok);
}
return 0;
}
Directive *interpreter(Directive *directives) {
Directive *directive;
Directive *last;
for (directive = directives; directive != NULL; directive = directive->next) {
if (interpret(directive)) {
/* This means this directive needs to be removed from the linked list. */
if (last == NULL) {
/* First directive. */
directives = directive->next;
} else {
last->next = directive->next;
}
} else {
last = directive;
}
}
return directives;
}
void add_to_fiwix_filelist(char *filename) {
/* Add the filename to fiwix-file-list.txt */
FILE *fiwix_list = fopen("/steps/lwext4-1.0.0-lb1/files/fiwix-file-list.txt", "r");
fseek(fiwix_list, 0, SEEK_END);
long size = ftell(fiwix_list);
char *contents = calloc(size, sizeof(char));
fseek(fiwix_list, 0, SEEK_SET);
fread(contents, 1, size, fiwix_list);
fclose(fiwix_list);
fiwix_list = fopen("/steps/lwext4-1.0.0-lb1/files/fiwix-file-list.txt", "w");
fwrite(contents, 1, size, fiwix_list);
fputs(filename, fiwix_list);
fputc('\n', fiwix_list);
fclose(fiwix_list);
}
/* Script generator. */
FILE *start_script(int id, int using_bash) {
/* Create the file /steps/$id.sh */
char *filename = calloc(MAX_STRING, sizeof(char));
strcpy(filename, "/steps/");
strcat(filename, int2str(id, 10, 0));
strcat(filename, ".sh");
add_to_fiwix_filelist(filename);
FILE *out = fopen(filename, "w");
if (out == NULL) {
fputs("Error opening output file ", stderr);
fputs(filename, stderr);
fputs("\n", stderr);
exit(1);
}
if (using_bash) {
fputs("#!/bin/bash\n", out);
fputs("set -e\n", out);
fputs("cd /steps\n", out);
fputs(". ./bootstrap.cfg\n", out);
fputs(". ./env\n", out);
fputs(". ./helpers.sh\n", out);
} else {
fputs("set -ex\n", out);
fputs("cd /steps\n", out);
output_config(out);
FILE *env = fopen("/steps/env", "r");
char *line = calloc(MAX_STRING, sizeof(char));
while (fgets(line, MAX_STRING, env) != 0) {
/* Weird M2-Planet behaviour. */
if (*line == 0) {
break;
}
fputs(line, out);
line = calloc(MAX_STRING, sizeof(char));
}
fclose(env);
}
return out;
}
void output_call_script(FILE *out, char *type, char *name, int using_bash, int source) {
if (using_bash) {
if (source) {
fputs(". ", out);
} else {
fputs("bash ", out);
}
} else {
fputs("kaem --file ", out);
}
fputs("/steps/", out);
fputs(type, out);
fputs("/", out);
fputs(name, out);
fputs(".sh\n", out);
}
void output_build(FILE *out, Directive *directive, int pass_no, int using_bash) {
if (using_bash) {
fputs("build ", out);
fputs(directive->arg, out);
fputs(" pass", out);
fputs(int2str(pass_no, 10, 0), out);
fputs(".sh\n", out);
} else {
fputs("pkg=", out);
fputs(directive->arg, out);
fputs("\n", out);
fputs("cd ${pkg}\n", out);
fputs("kaem --file pass", out);
fputs(int2str(pass_no, 10, 0), out);
fputs(".kaem\n", out);
fputs("cd ..\n", out);
}
}
void generate_preseed_jump(int id) {
FILE *out = fopen("/preseed-jump.kaem", "w");
fputs("set -ex\n", out);
fputs("PATH=/usr/bin\n", out);
fputs("bash /steps/", out);
fputs(int2str(id, 10, 0), out);
fputs(".sh\n", out);
fclose(out);
}
void generate(Directive *directives) {
/*
* We are separating the stages given in the mainfest into a bunch of
* smaller scripts. The following conditions call for the creation of
* a new script:
* - a jump
* - build of bash
*/
int counter = 0;
/* Initially, we use kaem, not bash. */
int using_bash = 0;
FILE *out = start_script(counter, using_bash);
counter += 1;
Directive *directive;
Directive *past;
char *filename;
int pass_no;
for (directive = directives; directive != NULL; directive = directive->next) {
if (directive->type == TYPE_BUILD) {
/* Get what pass number this is. */
pass_no = 1;
for (past = directives; past != directive; past = past->next) {
if (strcmp(past->arg, directive->arg) == 0) {
pass_no += 1;
}
}
output_build(out, directive, pass_no, using_bash);
if (strncmp(directive->arg, "bash-", 5) == 0) {
if (!using_bash) {
/*
* We are transitioning from bash to kaem, the point at which "early
* preseed" occurs. So generate the preseed jump script at this point.
*/
generate_preseed_jump(counter);
}
using_bash = 1;
/* Create call to new script. */
output_call_script(out, "", int2str(counter, 10, 0), using_bash, 0);
fclose(out);
out = start_script(counter, using_bash);
counter += 1;
}
} else if (directive->type == TYPE_IMPROVE) {
output_call_script(out, "improve", directive->arg, using_bash, 1);
} else if (directive->type == TYPE_JUMP) {
/*
* Create /init to call new script.
* We actually do this by creating /init.X for some number X, and then
* moving that to /init at the appropriate time.
*/
filename = calloc(MAX_STRING, sizeof(char));
if (using_bash) {
fputs("mv /init /init.bak\n", out);
/* Move new init to /init. */
strcpy(filename, "/init.");
strcat(filename, int2str(counter, 10, 0));
fputs("cp ", out);
fputs(filename, out);
fputs(" /init\n", out);
fputs("chmod 755 /init\n", out);
} else {
strcpy(filename, "/kaem.run.");
strcat(filename, int2str(counter, 10, 0));
fputs("cp ", out);
fputs(filename, out);
fputs(" /kaem.run\n", out);
fputs("cp /usr/bin/kaem /init\n", out);
fputs("chmod 755 /init\n", out);
}
output_call_script(out, "jump", directive->arg, using_bash, 1);
fclose(out);
/*
* This cannot go before here as builder-hex0 does not like having
* multiple files open at once!
*/
add_to_fiwix_filelist(filename);
if (using_bash) {
out = fopen(filename, "w");
if (out == NULL) {
fputs("Error opening /init\n", stderr);
exit(1);
}
fputs("#!/bin/bash\n", out);
} else {
out = fopen(filename, "w");
if (out == NULL) {
fputs("Error opening /kaem.run\n", stderr);
exit(1);
}
fputs("set -ex\n", out);
}
output_call_script(out, "", int2str(counter, 10, 0), using_bash, 0);
fclose(out);
out = start_script(counter, using_bash);
counter += 1;
} else if (directive->type == TYPE_MAINT) {
output_call_script(out, "maint", directive->arg, using_bash, 1);
}
}
fclose(out);
}
void main(int argc, char **argv) {
if (argc != 2) {
fputs("Usage: script-generator <script>\n", stderr);
exit(1);
}
FILE *in = fopen(argv[1], "r");
if (in == NULL) {
fputs("Error opening input file\n", stderr);
exit(1);
}
Directive *directives = tokenizer(in);
fclose(in);
load_config();
directives = interpreter(directives);
generate(directives);
FILE *config = fopen("/steps/bootstrap.cfg", "w");
output_config(config);
fclose(config);
}

View File

@ -9,20 +9,11 @@
set -ex
mkdir -p ${PREFIX} ${BINDIR} ${LIBDIR} ${INCDIR} ${SRCDIR} ${TMPDIR} /dev
# Temporarily change PATH
PATH=/${ARCH_DIR}/bin
# Set commonly used variables
sysa=/sysa
DISTFILES=/sysa/distfiles
PREFIX=/usr
BINDIR=${PREFIX}/bin
LIBDIR=${PREFIX}/lib
INCDIR=${PREFIX}/include/mes
SRCDIR=${PREFIX}/src
TMPDIR=/tmp # tmpdir is needed for patch to work
mkdir -p ${PREFIX} ${BINDIR} ${LIBDIR} ${INCDIR} ${SRCDIR} ${TMPDIR}
# Remove remaining dependencies on /bin (stage0-posix directory)
cp /${ARCH_DIR}/bin/blood-elf ${BINDIR}/blood-elf
cp /${ARCH_DIR}/bin/catm ${BINDIR}/catm
@ -63,10 +54,14 @@ chmod 755 ${BINDIR}/replace
chmod 755 ${BINDIR}/rm
PATH=${BINDIR}
M2LIBC_PATH=/M2libc
cd ${sysa}
# mes envars
NYACC_PKG=nyacc-1.00.2
MES_PKG=mes-0.25
MES_PREFIX=${SRCDIR}/${MES_PKG}/build/${MES_PKG}
GUILE_LOAD_PATH=${MES_PREFIX}/mes/module:${MES_PREFIX}/module:${SRCDIR}/${MES_PKG}/build/${NYACC_PKG}/module
catm run2.kaem bootstrap.cfg run.kaem
chmod 755 run2.kaem
kaem --file run2.kaem
M2-Mesoplanet --architecture ${ARCH} -f script-generator.c -o script-generator
./script-generator /steps/manifest
kaem --file /steps/0.sh

View File

@ -1,118 +1,118 @@
2dac610769286171ca81e736d729f5227938596cf44a0a8a764009715c55d23b autoconf-2.52_0.tar.bz2
7345a49227ed69774e01097c514f1ebd3abaeed0b2b9136b7f5ee1b0fe573390 autoconf-2.53_0.tar.bz2
6acc512d0a0ea3a860f708893a157609b93947c257df25ae324230c5aeca405e autoconf-2.54_0.tar.bz2
234e67c19653777fed7779c0c88c7592ca21d916b3e08eb366f85ed0f3ad6a9a autoconf-2.55_0.tar.bz2
8881440a9d105ca313eaa2149e7eb89263284bd5cef7bbdd953da9ca79997879 autoconf-2.57_0.tar.bz2
35925617e155087cc34bd71bd609d49098dedf7c051cac5c231eac19852d247f autoconf-2.59_0.tar.bz2
22418f18b0dbf0476efb1823dcebdf70d7619113ca10076ba9b078ab3597a578 autoconf-2.54_0.tar.bz2
8e74f93f12599f883ba62fe2bf4f69c70270ce368f71aa782f8f42a36a752d19 autoconf-2.55_0.tar.bz2
1bd66ca8cc6300e192afe06cd90b1250f02ca64539a4f3e98a872333ec04f44b autoconf-2.57_0.tar.bz2
83235c739887f0d801e410e922553a6fd7723cbd0c9b2e96106e20538abb3a3b autoconf-2.59_0.tar.bz2
8912ae2a24ea40a7cd3ccab5e97dd109db7be4a86f40458ac836568aa7437b6a autoconf-2.61_0.tar.bz2
d5fcce4baea5e11f983a7e4b7148545ab6720bb4e010898c73387f6711be67f4 autoconf-2.64_0.tar.bz2
298dcf17a439adb306237b308e3c4ed3d376cb863ae0f0f08bfdf1f3199a548b autoconf-2.69_0.tar.bz2
8c2401edf1c68910005bbcb8b8e84727a46f7d9643d2ad1267bd0259078dadc4 autoconf-2.71_0.tar.bz2
6ff691e3ddd4f3d1796d28b07a2a96691dbd9801844c99ccbe660da59dabd74b autoconf-archive-2021.02.19_0.tar.bz2
6a5cc1eb9ebc7e0ace8365e4c4aad5607ad1878ec9a90b384b55f8399cdbcb14 autogen-5.18.16_0.tar.bz2
56cb475253b1175f09d69bc81a5b1d954f486c9b97b1a0ae3217e63d18f64573 autogen-5.18.16_0.tar.bz2
02a426e82a52d4a2cd7e73fe3dc5a2c58b3ed100f24a92c57e42511fd86e247c automake-1.10.3_0.tar.bz2
34925adeaa2876a5e068adeb17b71fe7c7105244c3cb5439d33f7406310674da automake-1.11.2_0.tar.bz2
a7bd12bd0c639783ce1c0e9f640cf004a87460bbda8154bc550c5e6884457b48 automake-1.15.1_0.tar.bz2
57100612d902537b72ee2fd3dfecc903f2ea3959f1a480af87c6a1ef9a9d7c03 automake-1.16.3_0.tar.bz2
1c7e09ac08f156960420fca1f6e8560c1855bf01b001a0648b56153d6ceb9c28 automake-1.6.3_0.tar.bz2
444131776779d1f27628088a817bfb8c9aa85f4b036b934794a71e484ec9bd70 automake-1.6.3_1.tar.bz2
e8ff13753943e43972a8cf1672819f001718ed38e5497cf7b554c21a507ba22b automake-1.7.8_0.tar.bz2
ef08694bf8e78ffcf56f9c8a63b0f189e301c06f02ab240e15e4c7fe354c2a0d automake-1.7_0.tar.bz2
e8ff13753943e43972a8cf1672819f001718ed38e5497cf7b554c21a507ba22b automake-1.7.8_0.tar.bz2
9922651b64ad2e29b944082f26db223008220155048f25d64df1f6d82071ff1c automake-1.8.5_0.tar.bz2
c5807850a377e4bb9aa4121d9781d145bdd80327626a9419630a75ce2c8d9c71 automake-1.9.6_0.tar.bz2
5078d40dbdf5910cf9e89853765342366c19d9f2638e103b8158facd5655b6f6 bash-5.2.15_0.tar.bz2
f6e0a6d1a10c399101d2178063918750d271dab4da3db56955acf77ce11b6ba4 bc-1.07.1_0.tar.bz2
7b8ea17311f22e987a39b814658c72b46201650c4dfbc707e8fd9eb42bf1ed28 binutils-2.30_0.tar.bz2
abc76e210e1cae4a02b56686ed555ef6e5167deccdb96c021718e93fdb420ec4 binutils-2.38_0.tar.bz2
d7aac3185d1b19193f535e2c5377e2e41be872d55a6ae9a3c3d14b488df88277 binutils-2.38_1.tar.bz2
f8a55bf656f950ee3c5cea48af03f552166f6db9926b78c78843f3cc52a6e22d bash-5.2.15_0.tar.bz2
ebc631ee8e9382650005984ec5f3910492ccb6fb2656b4c0af0f4afc16998906 bc-1.07.1_0.tar.bz2
28b38078f88d77ebfa8ad1a514a5724fe11581bdbfc72b79f087fa24986ac9cb binutils-2.30_0.tar.bz2
6eb26a856e1eb79a1b3f6d76e42138bf1b868fc5f229c3a1e22d3eb68dfb88ba binutils-2.38_0.tar.bz2
57e339eb76a5a0f4b7298d0071f83354911dda928f4aa54e47a21ebc9c8390a7 binutils-2.38_1.tar.bz2
f0bb18831983493b82fde53917e8d16c6a380761ac5e71e14769a82193fee788 bison-2.3_0.tar.bz2
df9539b52384757d927bca5a27b1b58325b6024b23b0470e557f135eb69bae30 bison-3.4.1_0.tar.bz2
fed9e13409f6378f97e8cef61e6faac992f3b767dfdac22f32453ff57cf29e7b bison-3.4.1_1.tar.bz2
44d143d9dcb4098138a8b8eee0e29de1c7e282b9582df153f75ae301336c0927 bison-3.4.1_2.tar.bz2
7018edd13a1dd5ba35fdc8be49af91b28901aad3080fdeebdb98b79f8a90d7ed bison-3.4.1_0.tar.bz2
41c9a95b11cf183524927f52f9f7e97a479e0261c0551f6a4c22690b931243db bison-3.4.1_1.tar.bz2
4a291da4dc1d2a49eeff6bd6017d0d91f804d0a8a2b701de9ed5c53cf5061fe4 bison-3.4.1_2.tar.bz2
6d5e4debdec03aee096dbcefcad878fb5c6a069f895ee7ade878d9eeb97fb83e bison-3.4.2_0.tar.bz2
80e541fc4d3dfce4451318f26c31ccfe580848139672bd437131cdfd5e3664b2 bzip2-1.0.8_0.tar.bz2
e196396a3073992ca4d8ce1606831e3a6e06fd22753f89b778eec01eed549a92 bzip2-1.0.8_0.tar.bz2
c511d571d24675a141258e0e198c5ed1bcfd4889ddd736ff8e25c0d97b44e2cf ca-certificates-3.88.1_0.tar.bz2
acd3ba50a33ea0172c3ca59e341a48e4233be48ded26fa031fd2e9417a2dfb31 coreutils-5.0_0.tar.bz2
692ec3f83fdd94a3687c764e6246f608e4600bc8f9fec953a0b23617ad24d08d coreutils-5.0_0.tar.bz2
09092e187588c5d33c023ac41671b367aef9f7ee967d2c7c03430b33cc03f251 coreutils-6.10_0.tar.bz2
b19f9c44fa7711b93f62a6e7d7696219a819b7331c16662264acc43f7bd61251 coreutils-8.32_0.tar.bz2
d65348e9abcb961b6d060acb875b6ca3d75c14b1519426075d4644c6196b0ef2 curl-7.88.1_0.tar.bz2
93d5319fc83ea992f1db0fd163b4106b8bbb164475af40ce496244fed2a17422 curl-7.88.1_1.tar.bz2
0a11416b8d49f4fdf81e05ba81cc43fa3f33504f2c493935a3a7e9dbcb10a035 dhcpcd-10.0.1_0.tar.bz2
f49900486ae7f0c8107d729b71ede155ee44544cdf8d562b50fbea4095bd05b2 coreutils-8.32_0.tar.bz2
a133ec4b2c1c913821743a97bbb6e6842d67999c12c09dc821014c4e0661c365 curl-7.88.1_0.tar.bz2
2afc7d5f899a43807003f743ba2f173bbc14de836bd14f89d3991c73b56b37d8 curl-7.88.1_1.tar.bz2
1d4dec2d1885a6b5499a0f0d55e9c2c65dab532c4c593d848b6a542f67789627 dhcpcd-10.0.1_0.tar.bz2
c4008ae6b168aee4120b0f3624a1875f9e413d8f0c637708b8b04a1fb5be173c diffutils-2.7_0.tar.bz2
bda6afcd3a390a34a57443269a4857ccc470129f7a557981778c145fd841cbd1 dist-3.5-236_0.tar.bz2
1219dc5ffb33251b3b8e5ee2d605f5a648acccbc593ad766004441e9904e350f e2fsprogs-1.45.7_0.tar.bz2
dd2bc9708213816b752ea40cd7ff4d5b89336be47b3c76b2aff683708f9dcbbc ed-1.4_0.tar.bz2
9a680b6aaabd7c301438579389c500cce72472af3d78d8ba8f88c99feb9cc721 file-5.44_0.tar.bz2
5984d3f2d5513dd04dc97619e2809d634fc7e3692f36f770e0202a61b6b2921d findutils-4.2.33_0.tar.bz2
3a4c5143a241364019afd39af067f1e8433bab78b04096870d9bf2c70ec6ded8 e2fsprogs-1.45.7_0.tar.bz2
9c6f7e156f299f1d0948537e28f00d40e727a3debae3cce158e9bce827136214 ed-1.4_0.tar.bz2
0061d240f9bb2bb534db7003ddcc4eae9981954ad72e8f41ff1d76dc449ebd37 file-5.44_0.tar.bz2
d1db172ab3ea159cad1d76a7de9ec92fa8fec33270ddce16e304ece908dd1344 findutils-4.2.33_0.tar.bz2
41902ec0383ea977a8d008dee37150e022e0714cd99f54c37f29c153464b758a flex-2.5.11_0.tar.bz2
b3a8d59229289ca5a1de6a24c9c828d2847144f6662e0d5b7f41e7ff6e57abaa flex-2.5.33_0.tar.bz2
408131b1c033a5f8a6845997b049784be0b466cec107a71270e5a04dae2c1e6c flex-2.6.4_0.tar.bz2
5ff7fbe16b55563719b108260bd6a34ebabab0465d758ca98cba522932532e45 gawk-3.0.4_0.tar.bz2
6de1c1380026ef9948387e665610185b6014f47a80453177a6c81898c95cbbd3 gc-8.0.4_0.tar.bz2
374b54f568d7c67eb91f68a95b09322c9f6dc9c55cc6d49803ca3f5a8a3f6dbc gcc-10.4.0_0.tar.bz2
e2af44250ca4a29d505ddd7182db7f9c702d7dedcc0604d6f8ddac3872a0c057 gcc-13.1.0_0.tar.bz2
b09580c3972ff4e5f6e624bdc83d5328ce017422e0b92a7c170b51b6f04a47d2 gcc-4.0.4_0.tar.bz2
c16e9eaab6ac62df3a2a880f35c8da413be150fa00b66f992e37a1b411f32bcf gcc-4.0.4_1.tar.bz2
ed1eadc2b40eb3716801eaeaff0dbbc28c79101cf7880753d150bc8f2a4439c6 gcc-4.7.4_0.tar.bz2
872eabeff12a0b1b9dc2bd146f2c1e493597281795548377ff1ec5f6a1853e88 gcc-10.4.0_0.tar.bz2
4f50d8f5e1f123a8e6d34dff1d5892f79d250f2fb5d7fa2a94cff1f2e8f9649c gcc-13.1.0_0.tar.bz2
526c3710b5067bd2fc869371541d7e71dcff1cffcba7ddecabedc33967e19e2c gcc-4.0.4_0.tar.bz2
c1bf792e90df13bf7a24d3f8ce3939fd96ff61b8117e4dcef75605974f3fcf25 gcc-4.0.4_1.tar.bz2
7ac087bf006188154c28401d0c875ede56076c19d41bc54ffa0d7cc18ce40800 gcc-4.7.4_0.tar.bz2
dc67fc1b132fa3945349efe74c5b2197bd0b6babf4d29d2deddd04f09d9af680 gettext-0.21_0.tar.bz2
309282ba840f80b5e10897b1221f3ff3329b9e05b982c788d03652f411974524 gmp-6.2.1_0.tar.bz2
f5917ffad5dd282d5ea17e791b470455c328ea0ebc845ed5ec80937a8d0eb933 gperf-3.1_0.tar.bz2
67d706423e079a9cd764fd9607027d296c0ff2380c1104006a2230a299eb2c1d grep-2.4_0.tar.bz2
0939a34d58ff31e2c234f6f47f964633ceae4839de49ce368ad027c016850d58 grep-3.7_0.tar.bz2
d4c6b39136bbdb4a213a4229c5c460a6abefcda76285e4019d63e61382fbb8e8 guile-3.0.9_0.tar.bz2
9dacbb0d2a12585079ba2527af5bb165337aa6fe68fa42b93842abe3b8d46ef6 guile-3.0.9_0.tar.bz2
8d2015b87337abbf287f7a39ee4cf53514120b5d3e90a93fe7d533dcc43f14fa help2man-1.36.4_0.tar.bz2
72a0f7b561b6ef5dd29f9ddb1f4fd61a60230e41c6f18967afa8af40bfdf5473 kbd-1.15_0.tar.bz2
fd35fc5e14e7cb3c018964c43bf24dec2b3575d8fea38da3a2ea93349806a33c kexec-linux-1.0.0_0.tar.bz2
ca33ded1a8769dca42d6a1f9c05395e8da856fd9eecbb747cccb57d20b84459c kexec-tools-2.0.22_0.tar.bz2
a3f47ec4d26387952b22791d4d7d6837b90d81515d0a5ffe2804cf492fb090e1 libarchive-3.5.2_0.tar.bz2
f650c3b24de6edd49cd662c9e9ce11f7b0b5ea6df66d561b46a032b08fc34faa kbd-1.15_0.tar.bz2
3e3bc64af937c351be2538bb89de99f36ffc240721c32fcc84a76769e235ed66 kexec-linux-1.0.0_0.tar.bz2
1be7bf0319635b8bd22fd3c1a5a88ea267730a9a2e3cfff37473a5fea0779efb kexec-tools-2.0.22_0.tar.bz2
453c10220178f097e1ab26fac6dffbee63b61890cdb8d7d24dcd6acad6ad08a3 libarchive-3.5.2_0.tar.bz2
36550df491767bb24d2ccab304ce70a3b4956e7c0c0e0c343d922fd57cdafbdd libatomic_ops-7.6.10_0.tar.bz2
b39826742e236890f3562cdf19492e7ef4224b271f3e75ddeab1f07982b03ebe libffi-3.3_0.tar.bz2
daae709e98d2df2190d1d13b4e86f7f3fe90fa7a975282fe0bb03289b6539f29 libtool-2.2.4_0.tar.bz2
c1577cee0b82534699dc4385ecea9f521516303f773216d00bc30e4bf0053758 libtool-2.4.7_0.tar.bz2
6cefa575362149620f8008a32c8af54f0198a18bc6ab910bd3cead196c1507d7 libtool-2.4.7_0.tar.bz2
503007bbcddcf4e49d26514c59b4c9501f8b42f0c994a59dfdc388b1ae6b7900 libunistring-0.9.10_0.tar.bz2
1d07aaf7049be45853fd409340cdb52bb3a1b6dfa4dbc8b69358c1ee966cd67f linux-4.9.10_0.tar.bz2
2fd5bec0c086cb89596f14894cbf078b3d1e990d297ba02b6cc4135e7d64996b linux-headers-5.10.41_0.tar.bz2
e10734d700e3ab870374d3f37f6e6cb394d6ba7e2da6f4e70bb324e834b0ad7f linux-4.9.10_0.tar.bz2
d15c922973c15a8206e09020e8cfe6a78f7e93614de212f2b37ff80163799c6c linux-headers-4.9.10_0.tar.bz2
3864f2c66516fc4f5086f626f4da2b2a7635e21babca86ba478f866920868e2b m4-1.4.7_0.tar.bz2
cc203f338771ed1a99df17310bbe3e4885638d42141af8d0b3e8ed987e0fccca make-3.82_0.tar.bz2
e69554b0a77b419ddd5d0a0e418ba4005ecd0f6784c92a6928a0270bd929a098 make-3.82_0.tar.bz2
6d24960d6a987f68a7e0e3abf6edb52d2e0fe4c86f6ba45327e9634dbf7d40b4 make-4.2.1_0.tar.bz2
17cd976bc0f6e897c6fffe43dd7c55d93ce0adadf1b4dc72925b80e2d266519f mpc-1.2.1_0.tar.bz2
98a9f55c01ed375fae21913284e7fa07ff434c0810f34d791f3fbaa1df221302 mpfr-4.1.0_0.tar.bz2
a724c91a43e282c3d338a977e4eeac3b970df241db7872f9d5cf27984b609814 musl-1.1.24_0.tar.bz2
2a03a3707593997a0e03ce3aa6b2ee647cf2e5bfe1deb028357a2dfab56e33e2 musl-1.1.24_1.tar.bz2
12dfbee21a78220b4eb9fb843b6a00dd50c5849ffc4754b78209369499e3fefe musl-1.1.24_0.tar.bz2
8d09bb24659023897cacf959068cdd492acc965777d7fb49e1888c14e867b36d musl-1.1.24_1.tar.bz2
b79e0f8a39ba8880d43aa27551b72915655c62af39125e1f4ac8f8e69e71aaca musl-1.1.24_2.tar.bz2
81f79a0faf58e105c5f12d9f538d3ea7578a3b361e633ab8f47324ec23ec9de6 musl-1.2.4_0.tar.bz2
6dc5e763b747b66f72692c6820d7f46b7f4cf2e2fe05229a1d01c03919c1c936 musl-1.2.4_1.tar.bz2
538a65e8a55d476099f403ef4b3d13265022efb34d365124663f320262e04f3a musl-1.2.4_2.tar.bz2
97351f0df3d08ffdbe728a4b7fb36f91b1d83396be13ef6005ce62b9b62a9e07 openssl-1.1.1l_0.tar.bz2
61eedd6037ed342d069c48cf81792f9bd131ae2e9b937cd5c5e799f62d88c15c patch-2.7.6_0.tar.bz2
107548dd69ff4d5dfceb5891eed8a237cc6a22fd65915b44c838be1eba07668b musl-1.2.4_2.tar.bz2
c490016e49bbf77e7f63071f7aa60e8290a0c67f017846def1c3f65bd10d5712 openssl-1.1.1l_0.tar.bz2
71864d042cdc564b65eab21360902c714e9b43f80a19689c5600589529b267e7 patch-2.7.6_0.tar.bz2
914a7abf36a64723b6e9f9b0b6ccd19c8e544fa798896a2bb1151dc341890c22 perl-5.000_0.tar.bz2
887d835562d471653bcda60e652fceb4b3ef58a83321a4eb5af0431dc182781b perl-5.003_0.tar.bz2
74d64a8af080022432fa94dba449090419d25b103d247710dc0b6102a4ad86a6 perl-5.10.1_0.tar.bz2
71ad3cadba5801cb19d4520825d4b3606713807b1eaa5eb3c49b3149bc2675ad perl-5.32.1_0.tar.bz2
9fa8850897248d77d554caa2b3d52e7890308cbf28750ffc24c09f498aee563c perl-5.6.2_0.tar.bz2
b86fc586d72a6d204d0b9017afe17aa2439529e13f43befc56648b78de17c8f8 perl5.004-05_0.tar.bz2
451ae6bb6e996a1c857fe92ec379654413fadec180c6477cf5fd4b5d7a079e26 perl5.005-03_0.tar.bz2
74d64a8af080022432fa94dba449090419d25b103d247710dc0b6102a4ad86a6 perl-5.10.1_0.tar.bz2
fdccd3ba27a44d2149f159040414a04b39bfc72673ba36f50051b61199cc425c perl-5.32.1_0.tar.bz2
9fa8850897248d77d554caa2b3d52e7890308cbf28750ffc24c09f498aee563c perl-5.6.2_0.tar.bz2
1b9d4260edf7b2241d10e4c4ad17d0f90047bd4bf42f2487a7133902529e9dfe pkg-config-0.29.2_0.tar.bz2
5c4d4ff26c44b92caf08350f0e24f97b343961c4fd73f511f6bcef6a5e645b3f python-2.0.1_0.tar.bz2
f0c7bb60faae8eaf6960dfaad43acc7e30d5487ae114e44ec3c184c946adbc6f python-2.0.1_1.tar.bz2
5163e798e204b0e4ea1ab5d513ad618e11fb6dd01414991f7c7408dc74d54400 python-2.3.7_0.tar.bz2
ce21de104f50a65012f42df46b53beaf1dc2d8c5bf8f09ad20f80f64a2eb4d68 python-2.3.7_1.tar.bz2
2788ab6ae1c411898de035aadfdbed9b77812c73d9c68a79813390d6f1e3f87f python-2.5.6_0.tar.bz2
eba41b855f378e004648b1b3453485d2d4401cd72cf7b993c1be06b7cebf71a2 python-3.1.5_0.tar.bz2
e10a0eceb1fcb9ca80dfcaf53bfa0d311adbaccdaf6846a6c5abfbea1e7db879 python-3.1.5_1.tar.bz2
bc87d4b8b0d2f26ed7d632c73ef9cd937bc9b6cb3bdcb57fdea78d29e38722bc python-3.11.1_0.tar.bz2
be89de80f75679c07e59f72b8d3ee4f14edcaa306dccd9d8a2c8adbb83245a43 python-3.3.7_0.tar.bz2
e4a6dd6ff78b4f46e17e2b867e1562e1fa3a6c75db890c136818382d31619b78 python-3.4.10_0.tar.bz2
1e0c73270bec02c323981d75ce4c731677672719ea34abf06ba145b56aae178e python-3.8.16_0.tar.bz2
d4a263a4039b8d18ab95b5a7188a5c8b0defdf17d1cf899bf23a597be2df0658 python-2.0.1_0.tar.bz2
95ecbf909a8781d77e9b89e6ff3dc39e3ed702aebdec8b0a491df2dd4af8c780 python-2.0.1_1.tar.bz2
14b20bd76f6dfab0cc19141fd8d39c2841227b3876e5d107b1b57b05a51a83aa python-2.3.7_0.tar.bz2
5395d185003b22c607eb55a5b9f1adca5bbe178e7c774faabe758d0499936397 python-2.3.7_1.tar.bz2
374fc8c2577d681b7aa2670000fcc2450e2b50eb1cc8d739994ece69f83f4155 python-2.5.6_0.tar.bz2
e1321250c6421515f982a89ee4ceb8a8b7d2ecc3e192c7c7ede58e98f2bc75de python-3.11.1_0.tar.bz2
8f096d93f799a6575bae06a578625b92a888c25ed6b4d296173fc20fcadb003a python-3.1.5_0.tar.bz2
fb123d00e591452a6f077aaa8aa22ab8693e665ffa95e185a2bf79883d3d4684 python-3.1.5_1.tar.bz2
a9b73271407427f749406e1d3eabd51f627fd0fbe92332b792eeff1b9bfc44a5 python-3.3.7_0.tar.bz2
f95ce9de6002c47d82c41804e943a7079614fe7bc669fba15fe4552f9f08a7e3 python-3.4.10_0.tar.bz2
18bf5480d894d65bb11cad9d8591410e8a3b399f6eef3568d45144c363cd7d43 python-3.8.16_0.tar.bz2
6081832f1fc258df7dd927986821991b49fa78a71b76f4b37b5c34a8ebc9bc86 sed-4.0.9_0.tar.bz2
e58d8ec46c5b31175de9598bf0da214b88ccbd4cca7a787f3d048c44edaf3ceb sed-4.8_0.tar.bz2
912d8f344104f1322255d6210c7c7e1371413ab530b2c6796e6aa565c74bf647 tar-1.34_0.tar.bz2
a297b20252833d5c7b95ca343c85e84f9e5262e71beab9176ccf542833b75b4e tcc-0.9.27_0.tar.bz2
41a4b0fbf461dd26ecd31d77b300c979a4decae185c9e2d50c0470bc49d0b893 tcc-0.9.27_1.tar.bz2
cbfc578c709f677ec3e9792a8620e4e2a88d13d93969fd54aac93e4a29c2604d tcc-0.9.27_2.tar.bz2
d5d0df210248a385ae255cc5651369108e9a71fa8668821a6b1ed30a8d7364a1 tcc-0.9.27_0.tar.bz2
79276f54bc57933b6002e5511e6d8d88e22159dcf1cbbc9da763c38691a2c628 tcc-0.9.27_1.tar.bz2
31b5cbfec69d8037cc7f788c658f6fcd8c88794ecba34a2c5724bf6223b210f5 tcc-0.9.27_2.tar.bz2
2b503cd31d3326ac1ed0eb9f506ac93c93770da51164e152a812cd248961069c tcc-0.9.27_3.tar.bz2
50ebaa1d8fcc4a03a43d431eb71e2f435cc8712ae47d400564df3716037d553a texinfo-6.7_0.tar.bz2
a8e53f863b2ab7aa027ed5522702b451afd524b2c09d2f3d0daba1f460b26c91 util-linux-2.19.1_0.tar.bz2
229d9189adac10ad2a2c76fc147a4c317fc5b34026cef1c47edc9159aee480da util-linux-2.19.1_0.tar.bz2
5a1fdd2b42080f3b4808ceb1bf80a95873e614a25524545e6803b7d9f1fd5605 which-2.21_0.tar.bz2
17aa8a94450f3bb9fe6f2c6f59dde8aa6194f951bf3ab58249cb75ad472e864d xz-5.4.1_0.tar.bz2
3fade2079cc91f2c5624ff7247220059caee82e7de493332103d7a78155400b2 xz-5.4.1_0.tar.bz2
ca8ec9876a7334f5f87e1159e0efe343b8b497ffb0dea8b548223035ecd67f9e zlib-1.2.13_0.tar.bz2

View File

@ -0,0 +1 @@
dd42ffbc30919b13693cbd58536599907d057dc58aabde2b2b1e36ec0475e694 /usr/bin/bash

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