Note

The Funtoo Linux project has transitioned to "Hobby Mode" and this wiki is now read-only.

Frankenchroot

From Funtoo
Jump to navigation Jump to search

Funtoo binfmt_misc user mode Qemu chroot Guide: aka (Franken chroot)

Setting Up Your Filesystem

Exporting Your Remote Mounts with NFS

   /etc/exports - NFS file systems being exported
# /etc/exports: NFS file systems being exported.  See exports(5).
/ 
192.168.0.0/24(insecure,no_root_squash,nohide,rw,sync,no_subtree_check)
/boot/ 
192.168.0.0/24(insecure,no_root_squash,nohide,rw,sync,no_subtree_check)
/dev/ 
192.168.0.0/24(insecure,no_root_squash,nohide,rw,sync,no_subtree_check,fsid=77)

Mounting Your NFS Exports Locally and Binding Pseudo Filesystems

root # mount foo.local:/ /mnt/piroot
root # mount -t proc /proc /mnt/piroot/proc
root # mount --rbind /sys /mnt/piroot/{sys,dev} 
root # mount --make-rslave /mnt/piroot/{sys,dev} 
root # mount -t devpts none /mnt/piroot/dev/pts
   Note

You can safely ignore setting up NFS exports and mount the target filesystem locally with an sdcard reader if you desire. Mounting over NFS just makes for a more versatile setup without the need to transfer sdcards.

   Tip

(For Better Performance!) mount a tmpfs on top of /mnt/piroot/var/tmp/portage

root # mount -v -t tmpfs -o size=8G,mode=775,uid=portage,gid=portage,nr_inodes=0 tmpfs /mnt/piroot/var/tmp/portage


Local Configuration

Editing make.conf

First, add the following to /etc/portage/make.conf:

   /etc/portage/make.conf - Portage make.conf file
QEMU_USER_TARGETS="aarch64 arm"
FEATURES="-sandbox -ipc-sandbox -usersandbox candy"

Editing package.use

Then, edit /etc/portage/package.use:

   /etc/portage/package.use - Portage package.use file
app-emulation/qemu static-user
dev-libs/glib static-libs
sys-apps/attr static-libs
sys-libs/zlib static-libs
dev-libs/libpcre static-libs
   Warning

You WILL need to have updated to Funtoo-1.3-release and emerged the latest No results ebuild as it has fixed the static library creation needed to compile and run Qemu.

Emerging Qemu

Finally, emerge No results:

root # emerge -a app-emulation/qemu

Building and Installing the Wrapper Binary

   qemu-arm-wrapper.c (C source code) - qemu arm wrapper
/*
     * Call QEMU binary with additional "-cpu cortex-a7" argument.
     *
     * Copyright (c) 2018 sakaki <sakaki@deciban.com>
     * License: GPL v3.0+
     *
     * Based on code from the Gentoo Embedded Handbook
     * ("General/Compiling_with_qemu_user_chroot")
     */

    #include <string.h>
    #include <unistd.h>

    int main(int argc, char **argv, char **envp) {
        char *newargv[argc + 3];

        newargv[0] = argv[0];
        newargv[1] = "-cpu";
        newargv[2] = "cortex-a7";

        memcpy(&newargv[3], &argv[1], sizeof(*argv) * (argc -1));
        newargv[argc + 2] = NULL;
        return execve("/usr/local/bin/qemu-arm", newargv, envp);
    }
root # gcc -static -O3 -s -o qemu-arm-wrapper qemu-arm-wrapper.c
root # cp -av /usr/bin/qemu-arm /mnt/piroot/usr/local/bin/qemu-arm
root # cp -av qemu-arm-wrapper /mnt/piroot/usr/local/bin/qemu-arm-wrapper

Setting up binfmt_misc and Starting the Service

root # echo ":arm:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-arm-wrapper:" > /proc/sys/fs/binfmt_misc/register
root # rc-service binfmt restart
root # rc-service binfmt status


   Warning
The preceding wrapper and binfmt_misc register string were for arm 32bit. They *MUST* be edited for aarch64.


   Tip

The following code will create the binfmt_misc register string for the arch you are emulating in usermode Qemu. This is only needed for targets other than the arm target already packaged for you above. Usage is as followed:

root # chmod +x masky
root # masky /path/to/foreign/binary
  • Paste the output to /proc/sys/fs/binfmt_misc/register
  • Change "arm" in the following code to whatever you want the name of the binfmt_misc name to be when it is registered
  • Change /usr/local/bin/qemu-arm-wrapper to the name of your wrapper
   masky (python source code) - masky
#!/usr/bin/python3
import sys
import struct
import string
import codecs

printable_chars = set(string.printable)
printable_chars = set()
def print_out_hexstring(hexstring):
    to_process = hexstring
    while len(to_process):
        ascii_value = chr(int(to_process[:2], 16))
        to_process = to_process[2:]
        if ascii_value in printable_chars:
            sys.stdout.write(ascii_value)
        else:
            sys.stdout.write("\\x" + "{0:02x}".format(ord(ascii_value)))

chunk_as_hexstring = ""
with open(sys.argv[1], 'rb') as f:
    for x in range(0,19):
       chunk_as_hexstring += f.read(1).hex()
mask_as_hexstring = "fffffffffffffffcfffffffffffffffffeffff"
mask = int(mask_as_hexstring, 16)
chunk = int(chunk_as_hexstring, 16)
out_as_hexstring = hex(chunk & mask)[2:]
sys.stdout.write(":arm:M::")
print_out_hexstring(out_as_hexstring)
sys.stdout.write(":")
print_out_hexstring(mask_as_hexstring)
sys.stdout.write(":/usr/local/bin/qemu-arm-wrapper:\n")


Chrooting and Letting the Magic Happen

Entering Franken Chroot

root # mv -v /mnt/piroot/etc/resolv.conf{,.orig}
root # cp -v -L /etc/resolv.conf /mnt/piroot/etc/
root # env -i HOME=/root TERM=$TERM /bin/chroot /mnt/piroot /bin/bash -l
root # export PS1="(Franken_Chroot) $PS1"

Exiting Franken Chroot and Final Thoughts

root # rm /etc/resolv.conf
root # mv -v /etc/resolv.conf{.orig,}
root # exit
root # umount -v /mnt/piroot/var/tmp/portage
root # umount -lR /mnt/piroot
root # sync