mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-28 20:44:26 +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.
|
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:
|
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.
|
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.
|
initramfs is just like <<initrd>>, but you also glue the image directly to the kernel image itself using the kernel's build system.
|
||||||
|
|
||||||
So the only argument that QEMU needs is the `-kernel`, no `-drive` not even `-initrd`! Pretty cool.
|
|
||||||
|
|
||||||
Try it out with:
|
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-buildroot --initramfs
|
||||||
|
./build-linux --initramfs
|
||||||
./run --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)"
|
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.
|
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.
|
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:
|
In this repo, leaking host information, and to make builds more reproducible, we are setting:
|
||||||
|
|
||||||
- user and date to dummy values
|
- user and date to dummy values with `KBUILD_BUILD_USER` and `KBUILD_BUILD_TIMESTAMP`
|
||||||
- hostname to the kernel git commit
|
- 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
|
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 = [
|
config_fragments = [
|
||||||
os.path.join(self.env['root_dir'], 'buildroot_config', 'default')
|
os.path.join(self.env['root_dir'], 'buildroot_config', 'default')
|
||||||
] + self.env['config_fragment']
|
] + self.env['config_fragment']
|
||||||
if self.env['initrd']:
|
if self.env['initrd'] or self.env['initramfs']:
|
||||||
configs.append('BR2_TARGET_ROOTFS_CPIO=y')
|
configs.append('BR2_TARGET_ROOTFS_CPIO=y')
|
||||||
# TODO Can't get rid of these for now with nice fragments on Buildroot:
|
# 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
|
# 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):
|
def build(self):
|
||||||
build_dir = self.get_build_dir()
|
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)
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
tool = 'gcc'
|
tool = 'gcc'
|
||||||
gcc = self.get_toolchain_tool(tool)
|
gcc = self.get_toolchain_tool(tool)
|
||||||
@@ -105,10 +103,12 @@ Run `make modules_install` after `make`.
|
|||||||
for i, config_fragment in enumerate(config_fragments):
|
for i, config_fragment in enumerate(config_fragments):
|
||||||
config_fragments[i] = os.path.join(self.env['linux_config_dir'], config_fragment)
|
config_fragments[i] = os.path.join(self.env['linux_config_dir'], config_fragment)
|
||||||
config_fragments.extend(self.env['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_fragment_path = os.path.join(build_dir, 'lkmc_cli_config_fragment')
|
||||||
cli_config_str = '\n'.join(self.env['config'])
|
self.sh.write_configs(cli_config_fragment_path, cli_configs, mode='w')
|
||||||
self.sh.write_string_to_file(cli_config_fragment_path, cli_config_str)
|
|
||||||
config_fragments.append(cli_config_fragment_path)
|
config_fragments.append(cli_config_fragment_path)
|
||||||
self.sh.cp(
|
self.sh.cp(
|
||||||
base_config_file,
|
base_config_file,
|
||||||
@@ -136,6 +136,7 @@ Run `make modules_install` after `make`.
|
|||||||
common_make_args +
|
common_make_args +
|
||||||
self.sh.add_newlines(self.env['extra_make_args'])
|
self.sh.add_newlines(self.env['extra_make_args'])
|
||||||
),
|
),
|
||||||
|
# https://github.com/cirosantilli/linux-kernel-module-cheat#proc-version
|
||||||
extra_env={
|
extra_env={
|
||||||
'KBUILD_BUILD_VERSION': '1',
|
'KBUILD_BUILD_VERSION': '1',
|
||||||
'KBUILD_BUILD_TIMESTAMP': 'Thu Jan 1 00:00:00 UTC 1970',
|
'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(
|
self.add_argument(
|
||||||
'--initramfs', default=False,
|
'--initramfs',
|
||||||
|
default=False,
|
||||||
)
|
)
|
||||||
self.add_argument(
|
self.add_argument(
|
||||||
'--initrd',
|
'--initrd',
|
||||||
default=False,
|
default=False,
|
||||||
help='''\
|
help='''\
|
||||||
Make Buildroot create a CPIO root filessytem, and make QEMU use it instead of
|
For Buildroot: create a CPIO root filessytem.
|
||||||
the default ext2.
|
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_images_dir'] = join(env['buildroot_build_dir'], 'images')
|
||||||
env['buildroot_rootfs_raw_file'] = join(env['buildroot_images_dir'], 'rootfs.ext2')
|
env['buildroot_rootfs_raw_file'] = join(env['buildroot_images_dir'], 'rootfs.ext2')
|
||||||
env['buildroot_qcow2_file'] = env['buildroot_rootfs_raw_file'] + '.qcow2'
|
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['staging_dir'] = join(env['out_dir'], 'staging', env['arch'])
|
||||||
env['buildroot_staging_dir'] = join(env['buildroot_build_dir'], 'staging')
|
env['buildroot_staging_dir'] = join(env['buildroot_build_dir'], 'staging')
|
||||||
env['target_dir'] = join(env['buildroot_build_dir'], 'target')
|
env['target_dir'] = join(env['buildroot_build_dir'], 'target')
|
||||||
@@ -601,6 +604,7 @@ Valid emulators: {}
|
|||||||
else:
|
else:
|
||||||
env['userland_quit_cmd'] = '/poweroff.out'
|
env['userland_quit_cmd'] = '/poweroff.out'
|
||||||
env['quit_init'] = 'init={}'.format(env['userland_quit_cmd'])
|
env['quit_init'] = 'init={}'.format(env['userland_quit_cmd'])
|
||||||
|
self.env['ramfs'] = self.env['initrd'] or self.env['initramfs']
|
||||||
|
|
||||||
# Kernel modules.
|
# Kernel modules.
|
||||||
env['kernel_modules_build_dir'] = join(env['kernel_modules_build_base_dir'], env['arch'])
|
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
|
# These cache sizes roughly match the ARM Cortex A75
|
||||||
# https://en.wikipedia.org/wiki/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.
|
# Generate a checkpoint after Linux boots, using the faster and less detailed CPU.
|
||||||
# The boot takes a while, be patient young Padawan.
|
# 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,
|
'--kdb', default=False,
|
||||||
)
|
)
|
||||||
self.add_argument(
|
self.add_argument(
|
||||||
'-l', '--gem5-restore', type=int,
|
'--gem5-restore', type=int,
|
||||||
help='''\
|
help='''\
|
||||||
Restore the nth most recently taken gem5 checkpoint according to directory
|
Restore the nth most recently taken gem5 checkpoint according to directory
|
||||||
timestamps.
|
timestamps.
|
||||||
@@ -231,12 +231,8 @@ Run QEMU with VNC instead of the default SDL. Connect to it with:
|
|||||||
vnc = ['-vnc', ':0', LF]
|
vnc = ['-vnc', ':0', LF]
|
||||||
else:
|
else:
|
||||||
vnc = []
|
vnc = []
|
||||||
if self.env['initrd'] or self.env['initramfs']:
|
|
||||||
ramfs = True
|
|
||||||
else:
|
|
||||||
ramfs = False
|
|
||||||
if self.env['eval'] is not None:
|
if self.env['eval'] is not None:
|
||||||
if ramfs:
|
if self.env['ramfs']:
|
||||||
initarg = 'rdinit'
|
initarg = 'rdinit'
|
||||||
else:
|
else:
|
||||||
initarg = 'init'
|
initarg = 'init'
|
||||||
@@ -504,9 +500,9 @@ Run QEMU with VNC instead of the default SDL. Connect to it with:
|
|||||||
if not qemu_executable_prebuilt:
|
if not qemu_executable_prebuilt:
|
||||||
cmd.extend(qemu_user_and_system_options)
|
cmd.extend(qemu_user_and_system_options)
|
||||||
if self.env['initrd']:
|
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']
|
rr = self.env['record'] or self.env['replay']
|
||||||
if ramfs:
|
if self.env['ramfs']:
|
||||||
# TODO why is this needed, and why any string works.
|
# TODO why is this needed, and why any string works.
|
||||||
root = 'root=/dev/anything'
|
root = 'root=/dev/anything'
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -269,9 +269,9 @@ class ShellHelpers:
|
|||||||
else:
|
else:
|
||||||
os.unlink(path)
|
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:
|
if config_fragments is None:
|
||||||
config_fragments = []
|
config_fragments = []
|
||||||
@@ -283,7 +283,7 @@ class ShellHelpers:
|
|||||||
with open(config_fragment, 'r') as config_fragment_file:
|
with open(config_fragment, 'r') as config_fragment_file:
|
||||||
for line in config_fragment_file:
|
for line in config_fragment_file:
|
||||||
config_file.write(line)
|
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'):
|
def write_string_to_file(self, path, string, mode='w'):
|
||||||
if mode == 'a':
|
if mode == 'a':
|
||||||
@@ -292,5 +292,5 @@ class ShellHelpers:
|
|||||||
redirect = '>'
|
redirect = '>'
|
||||||
self.print_cmd("cat << 'EOF' {} {}\n{}\nEOF".format(redirect, path, string))
|
self.print_cmd("cat << 'EOF' {} {}\n{}\nEOF".format(redirect, path, string))
|
||||||
if not self.dry_run:
|
if not self.dry_run:
|
||||||
with open(path, 'a') as f:
|
with open(path, mode) as f:
|
||||||
f.write(string)
|
f.write(string)
|
||||||
|
|||||||
Reference in New Issue
Block a user