Merge pull request #334 from fosslinux/simplify
Simplify + Sustainability
This commit is contained in:
commit
545bb42ca8
|
@ -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,7 +5,6 @@
|
|||
|
||||
tmp/
|
||||
kernel
|
||||
sysa/distfiles/
|
||||
sysc/distfiles/
|
||||
distfiles/
|
||||
__pycache__
|
||||
sysa/bootstrap.cfg
|
||||
steps/bootstrap.cfg
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
60
DEVEL.md
60
DEVEL.md
|
@ -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.
|
||||
|
|
206
README.rst
206
README.rst
|
@ -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 don’t 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 janneke’s 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 I’m 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. Here’s 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.in’s 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
}
|
|
@ -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",
|
||||
}
|
|
@ -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])
|
||||
|
|
|
@ -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
147
parts.rst
|
@ -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
|
||||
===========
|
||||
|
|
65
rootfs.py
65
rootfs.py
|
@ -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')
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
dd42ffbc30919b13693cbd58536599907d057dc58aabde2b2b1e36ec0475e694 /usr/bin/bash
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue