mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-25 19:21:35 +01:00
initfamfs: bring back to life. Was also easy!
This commit is contained in:
41
README.adoc
41
README.adoc
@@ -2617,6 +2617,8 @@ cat "$(./getvar run_dir)/run.sh"
|
||||
|
||||
Instead, we used the QEMU `-initrd` option to point to the `.cpio` filesystem that Buildroot generated for us.
|
||||
|
||||
Try removing that `-initrd` option to watch the kernel panic without rootfs at the end of boot.
|
||||
|
||||
When using `.cpio`, there can be no filesystem persistency across boots, since all file operations happen in memory in a tmpfs:
|
||||
|
||||
....
|
||||
@@ -2674,25 +2676,25 @@ Related: https://stackoverflow.com/questions/6405083/initrd-and-booting-the-linu
|
||||
|
||||
TODO: broken when we started building the Linux manually with `./build-linux` instead of Buildroot. Was working before, see e.g. 56738a1c70e50bf7b6d5fbe02372c5d277a8286f.
|
||||
|
||||
initramfs is just like <<initrd>>, but you also glue the image directly to the kernel image itself.
|
||||
|
||||
So the only argument that QEMU needs is the `-kernel`, no `-drive` not even `-initrd`! Pretty cool.
|
||||
initramfs is just like <<initrd>>, but you also glue the image directly to the kernel image itself using the kernel's build system.
|
||||
|
||||
Try it out with:
|
||||
|
||||
....
|
||||
./build-buildroot --initramfs -l
|
||||
./run --initramfs
|
||||
....
|
||||
|
||||
The `-l` (ell) should only be used the first time you move to / from a different root filesystem method (ext2 or cpio) to initramfs to overcome: https://stackoverflow.com/questions/49260466/why-when-i-change-br2-linux-kernel-custom-config-file-and-run-make-linux-reconfi
|
||||
|
||||
....
|
||||
./build-buildroot --initramfs
|
||||
./build-linux --initramfs
|
||||
./run --initramfs
|
||||
....
|
||||
|
||||
It is interesting to see how this increases the size of the kernel image if you do a:
|
||||
Notice how we had to rebuild the Linux kernel this time around as well after Buildroot, since in that build we will be gluing the CPIO to the kernel image.
|
||||
|
||||
Now, once again, if we look at the QEMU run command generated, we see all that QEMU needs is the `-kernel` option, no `-drive` not even `-initrd`! Pretty cool:
|
||||
|
||||
....
|
||||
cat "$(./getvar run_dir)/run.sh"
|
||||
....
|
||||
|
||||
It is also interesting to observe how this increases the size of the kernel image if you do a:
|
||||
|
||||
....
|
||||
ls -lh "$(./getvar linux_image)"
|
||||
@@ -2700,7 +2702,16 @@ ls -lh "$(./getvar linux_image)"
|
||||
|
||||
before and after using initramfs, since the `.cpio` is now glued to the kernel image.
|
||||
|
||||
In the background, it uses `BR2_TARGET_ROOTFS_INITRAMFS`, and this makes the kernel config option `CONFIG_INITRAMFS_SOURCE` point to the CPIO that will be embedded in the kernel image.
|
||||
Don't forget that to stop using initramfs, you must rebuild the kernel without `--initramfs`:
|
||||
|
||||
....
|
||||
./build-linux
|
||||
./run
|
||||
....
|
||||
|
||||
Also consider using <<linux-kernel-build-variants>> if you need to switch between initramfs and non initramfs often.
|
||||
|
||||
Setting up initramfs is very easy: our scripts just set `CONFIG_INITRAMFS_SOURCE` to point to the CPIO path.
|
||||
|
||||
http://nairobi-embedded.org/initramfs_tutorial.html shows a full manual setup.
|
||||
|
||||
@@ -5415,10 +5426,10 @@ Where the data comes from and how to modify it:
|
||||
|
||||
In this repo, leaking host information, and to make builds more reproducible, we are setting:
|
||||
|
||||
- user and date to dummy values
|
||||
- hostname to the kernel git commit
|
||||
- user and date to dummy values with `KBUILD_BUILD_USER` and `KBUILD_BUILD_TIMESTAMP`
|
||||
- hostname to the kernel git commit with `KBUILD_BUILD_HOST` and `KBUILD_BUILD_VERSION`
|
||||
|
||||
So the file contains something like:
|
||||
A sample result is:
|
||||
|
||||
....
|
||||
Linux version 4.19.0-dirty (lkmc@84df9525b0c27f3ebc2ebb1864fa62a97fdedb7d) (gcc version 6.4.0 (Buildroot 2018.05-00002-gbc60382b8f)) #1 SMP Thu Jan 1 00:00:00 UTC 1970
|
||||
|
||||
@@ -133,7 +133,7 @@ usually extra Buildroot targets.
|
||||
config_fragments = [
|
||||
os.path.join(self.env['root_dir'], 'buildroot_config', 'default')
|
||||
] + self.env['config_fragment']
|
||||
if self.env['initrd']:
|
||||
if self.env['initrd'] or self.env['initramfs']:
|
||||
configs.append('BR2_TARGET_ROOTFS_CPIO=y')
|
||||
# TODO Can't get rid of these for now with nice fragments on Buildroot:
|
||||
# http://stackoverflow.com/questions/44078245/is-it-possible-to-use-config-fragments-with-buildroots-config
|
||||
|
||||
11
build-linux
11
build-linux
@@ -64,8 +64,6 @@ Run `make modules_install` after `make`.
|
||||
|
||||
def build(self):
|
||||
build_dir = self.get_build_dir()
|
||||
if self.env['initrd'] or self.env['initramfs']:
|
||||
raise Exception('just trolling, --initrd and --initramfs are broken for now')
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
tool = 'gcc'
|
||||
gcc = self.get_toolchain_tool(tool)
|
||||
@@ -105,10 +103,12 @@ Run `make modules_install` after `make`.
|
||||
for i, config_fragment in enumerate(config_fragments):
|
||||
config_fragments[i] = os.path.join(self.env['linux_config_dir'], config_fragment)
|
||||
config_fragments.extend(self.env['config_fragment'])
|
||||
if self.env['config'] != []:
|
||||
cli_configs = self.env['config']
|
||||
if self.env['initramfs']:
|
||||
cli_configs.append('CONFIG_INITRAMFS_SOURCE="{}"'.format(self.env['buildroot_cpio']))
|
||||
if cli_configs:
|
||||
cli_config_fragment_path = os.path.join(build_dir, 'lkmc_cli_config_fragment')
|
||||
cli_config_str = '\n'.join(self.env['config'])
|
||||
self.sh.write_string_to_file(cli_config_fragment_path, cli_config_str)
|
||||
self.sh.write_configs(cli_config_fragment_path, cli_configs, mode='w')
|
||||
config_fragments.append(cli_config_fragment_path)
|
||||
self.sh.cp(
|
||||
base_config_file,
|
||||
@@ -136,6 +136,7 @@ Run `make modules_install` after `make`.
|
||||
common_make_args +
|
||||
self.sh.add_newlines(self.env['extra_make_args'])
|
||||
),
|
||||
# https://github.com/cirosantilli/linux-kernel-module-cheat#proc-version
|
||||
extra_env={
|
||||
'KBUILD_BUILD_VERSION': '1',
|
||||
'KBUILD_BUILD_TIMESTAMP': 'Thu Jan 1 00:00:00 UTC 1970',
|
||||
|
||||
10
common.py
10
common.py
@@ -255,14 +255,16 @@ Use the given directory as the Linux source tree.
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'--initramfs', default=False,
|
||||
'--initramfs',
|
||||
default=False,
|
||||
)
|
||||
self.add_argument(
|
||||
'--initrd',
|
||||
default=False,
|
||||
help='''\
|
||||
Make Buildroot create a CPIO root filessytem, and make QEMU use it instead of
|
||||
the default ext2.
|
||||
For Buildroot: create a CPIO root filessytem.
|
||||
For QEMU use that CPUI root filesystem initrd instead of the default ext2.
|
||||
See: https://github.com/cirosantilli/linux-kernel-module-cheat#initrd
|
||||
'''
|
||||
)
|
||||
|
||||
@@ -477,6 +479,7 @@ Valid emulators: {}
|
||||
env['buildroot_images_dir'] = join(env['buildroot_build_dir'], 'images')
|
||||
env['buildroot_rootfs_raw_file'] = join(env['buildroot_images_dir'], 'rootfs.ext2')
|
||||
env['buildroot_qcow2_file'] = env['buildroot_rootfs_raw_file'] + '.qcow2'
|
||||
env['buildroot_cpio'] = join(self.env['buildroot_images_dir'], 'rootfs.cpio')
|
||||
env['staging_dir'] = join(env['out_dir'], 'staging', env['arch'])
|
||||
env['buildroot_staging_dir'] = join(env['buildroot_build_dir'], 'staging')
|
||||
env['target_dir'] = join(env['buildroot_build_dir'], 'target')
|
||||
@@ -601,6 +604,7 @@ Valid emulators: {}
|
||||
else:
|
||||
env['userland_quit_cmd'] = '/poweroff.out'
|
||||
env['quit_init'] = 'init={}'.format(env['userland_quit_cmd'])
|
||||
self.env['ramfs'] = self.env['initrd'] or self.env['initramfs']
|
||||
|
||||
# Kernel modules.
|
||||
env['kernel_modules_build_dir'] = join(env['kernel_modules_build_base_dir'], env['arch'])
|
||||
|
||||
@@ -10,7 +10,7 @@ cmd="./run --arch '$arch' --emulator gem5 --eval-busybox '/gem5.sh'"
|
||||
|
||||
# These cache sizes roughly match the ARM Cortex A75
|
||||
# https://en.wikipedia.org/wiki/ARM_Cortex-A75
|
||||
restore='-l 1 -- --cpu-type=HPI --restore-with-cpu=HPI --caches --l2cache --l1d_size=64kB --l1i_size=64kB --l2_size=256kB'
|
||||
restore='--gem5-restore 1 -- --cpu-type=HPI --restore-with-cpu=HPI --caches --l2cache --l1d_size=64kB --l1i_size=64kB --l2_size=256kB'
|
||||
|
||||
# Generate a checkpoint after Linux boots, using the faster and less detailed CPU.
|
||||
# The boot takes a while, be patient young Padawan.
|
||||
|
||||
12
run
12
run
@@ -117,7 +117,7 @@ gem.op5 --debug-flags=Exec fs.py --cpu-type=HPI --caches
|
||||
'--kdb', default=False,
|
||||
)
|
||||
self.add_argument(
|
||||
'-l', '--gem5-restore', type=int,
|
||||
'--gem5-restore', type=int,
|
||||
help='''\
|
||||
Restore the nth most recently taken gem5 checkpoint according to directory
|
||||
timestamps.
|
||||
@@ -231,12 +231,8 @@ Run QEMU with VNC instead of the default SDL. Connect to it with:
|
||||
vnc = ['-vnc', ':0', LF]
|
||||
else:
|
||||
vnc = []
|
||||
if self.env['initrd'] or self.env['initramfs']:
|
||||
ramfs = True
|
||||
else:
|
||||
ramfs = False
|
||||
if self.env['eval'] is not None:
|
||||
if ramfs:
|
||||
if self.env['ramfs']:
|
||||
initarg = 'rdinit'
|
||||
else:
|
||||
initarg = 'init'
|
||||
@@ -504,9 +500,9 @@ Run QEMU with VNC instead of the default SDL. Connect to it with:
|
||||
if not qemu_executable_prebuilt:
|
||||
cmd.extend(qemu_user_and_system_options)
|
||||
if self.env['initrd']:
|
||||
extra_emulator_args.extend(['-initrd', os.path.join(self.env['buildroot_images_dir'], 'rootfs.cpio')])
|
||||
extra_emulator_args.extend(['-initrd', self.env['buildroot_cpio'], LF])
|
||||
rr = self.env['record'] or self.env['replay']
|
||||
if ramfs:
|
||||
if self.env['ramfs']:
|
||||
# TODO why is this needed, and why any string works.
|
||||
root = 'root=/dev/anything'
|
||||
else:
|
||||
|
||||
@@ -269,9 +269,9 @@ class ShellHelpers:
|
||||
else:
|
||||
os.unlink(path)
|
||||
|
||||
def write_configs(self, config_path, configs, config_fragments=None):
|
||||
def write_configs(self, config_path, configs, config_fragments=None, mode='a'):
|
||||
'''
|
||||
Write extra KEY=val configs into the given config file.
|
||||
Append extra KEY=val configs into the given config file.
|
||||
'''
|
||||
if config_fragments is None:
|
||||
config_fragments = []
|
||||
@@ -283,7 +283,7 @@ class ShellHelpers:
|
||||
with open(config_fragment, 'r') as config_fragment_file:
|
||||
for line in config_fragment_file:
|
||||
config_file.write(line)
|
||||
self.write_string_to_file(config_path, '\n'.join(configs), mode='a')
|
||||
self.write_string_to_file(config_path, '\n'.join(configs), mode=mode)
|
||||
|
||||
def write_string_to_file(self, path, string, mode='w'):
|
||||
if mode == 'a':
|
||||
@@ -292,5 +292,5 @@ class ShellHelpers:
|
||||
redirect = '>'
|
||||
self.print_cmd("cat << 'EOF' {} {}\n{}\nEOF".format(redirect, path, string))
|
||||
if not self.dry_run:
|
||||
with open(path, 'a') as f:
|
||||
with open(path, mode) as f:
|
||||
f.write(string)
|
||||
|
||||
Reference in New Issue
Block a user