Samsung Chromebook Plus XE513C24

Developer Mode

Note: After enabling developer mode, you will need to press Ctrl-D each time you boot, or wait 30 seconds to continue booting.

Enable booting from external storage

crossystem dev_boot_usb=1 dev_boot_signed_only=0

First Attempt Gentoo SD Image

Note: I'm doing the build from my Orange Pi 800 with the same RK3399 so no cross compile environment is required.

Preparing SD Card

Install the required tools onto the build system:

emerge --ask dev-embedded/u-boot-tools sys-apps/dtc sys-block/parted sys-boot/vboot-utils

Partion the sd card.

root #parted /dev/sdc mklabel gpt
root #parted -a optimal /dev/sdc unit mib mkpart Kernel 1 65
root #parted -a optimal /dev/sdc unit mib mkpart Root 65 100%

Depthcharge requires some specific parameters to be set. These signal the bootloader the presence of a valid kernel partition:

root #cgpt add -i 1 -t kernel -S 1 -T 5 -P 15 /dev/sdc

Create a filesystem on the root partition and mount it:

root #mkfs.ext4 /dev/sdc2
root #mount /dev/sdc2 /mnt/sdcard

Grabbed latest arm64 stage3 and extracted to /mnt/sdcard: https://distfiles.gentoo.org/releases/arm64/autobuilds/20240128T234815Z/stage3-arm64-openrc-20240128T234815Z.tar.xz

Also grabbed the latest portage snapshot as it doesn't appear its in the stage 3 and extracted to /var/db/repos/gentoo: https://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2

I copied my make.conf from my Orange Pi 800 as they both have the same rk3399 SOC.

# These settings were set by the catalyst build script that automatically
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.
COMMON_FLAGS="-march=armv8-a+crc+crypto -mtune=cortex-a72.cortex-a53 -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"

# WARNING: Changing your CHOST is not something that should be done lightly.
# Please consult https://wiki.gentoo.org/wiki/Changing_the_CHOST_variable before changing.
CHOST="aarch64-unknown-linux-gnu"

# NOTE: This stage was built with the bindist Use flag enabled

# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C.utf8
USE="-X gpm alsa -udev pulseaudio"
ACCEPT_LICENSE="-* @FREE @BINARY-REDISTRIBUTABLE"
LLVM_TARGETS="AArch64"
VIDEO_CARDS="panfrost"
Getting ready to Chroot

Copy over resolv.conf:

cp --dereference /etc/resolv.conf /mnt/sdcard/etc/

Setup binds:

root #mount --types proc /proc /mnt/sdcard/proc
root #mount --rbind /sys /mnt/sdcard/sys
root #mount --make-rslave /mnt/sdcard/sys
root #mount --rbind /dev /mnt/sdcard/dev
root #mount --make-rslave /mnt/sdcard/dev
root #mount --bind /run /mnt/sdcard/run
root #mount --make-slave /mnt/sdcard/run

Chroot in:

root #chroot /mnt/sdcard /bin/bash
root #source /etc/profile
root #export PS1="(chroot) ${PS1}"
Get sources and configure kernel
emerge --ask gentoo-sources

I stole the config from https://git.alpinelinux.org/aports/plain/testing/linux-gru/config I edited the config text and added the gentoo specific options required:

< # Linux/arm64 6.6.2 Kernel Configuration
---
> # Linux/arm64 6.6.13-gentoo Kernel Configuration
5c5
< CONFIG_CC_VERSION_TEXT="gcc (Alpine 13.2.1_git20231014) 13.2.1 20231014"
---
> CONFIG_CC_VERSION_TEXT="gcc (Gentoo 13.2.1_p20240113-r1 p12) 13.2.1 20240113"
7294a7295,7312
> 
> #
> # Gentoo Linux
> #
> CONFIG_GENTOO_LINUX=y
> CONFIG_GENTOO_LINUX_UDEV=y
> CONFIG_GENTOO_LINUX_PORTAGE=y
> 
> #
> # Support for init systems, system and service managers
> #
> CONFIG_GENTOO_LINUX_INIT_SCRIPT=y
> # CONFIG_GENTOO_LINUX_INIT_SYSTEMD is not set
> # end of Support for init systems, system and service managers
> 
> # CONFIG_GENTOO_KERNEL_SELF_PROTECTION is not set
> CONFIG_GENTOO_PRINT_FIRMWARE_INFO=y
> # end of Gentoo Linux

I manually applied both patch files found here: https://git.alpinelinux.org/aports/tree/testing/linux-gru/

Compiling the kernel:

make
make dtbs

Set the root password with passwd.

Set the timezone:

root #echo "America/Detroit" > /etc/timezone
root #emerge --config sys-libs/timezone-data

Setup locale:

vim /etc/locale.gen
locale-gen
eselect locale list
eselect locale set

Install some system tools and firmware (required for wireless):

emerge --ask linux-firmware wpa_supplicant dhcpcd syslog-ng cronie chrony e2fsprogs
rc-update add dhcpcd default
rc-update add syslog-ng default
rc-update add cronie default
rc-update add sshd default
rc-update add chronyd default

Configure hostname:

echo "hostname" > /etc/hostname
vim /etc/hosts
127.0.0.1     hostname.localdomain.lan hostname localhost
::1           hostname.localdomain.lan hostname localhost  

Set clock=“local” if your hardware clock is localtime

Setup a normal user:

useradd -m -G users,wheel,audio -s /bin/bash johndoe
passwd johndoe

Exit the chroot.

Create a swapfile (ensure you've exited the chroot):

fallocate -l 4G /mnt/sdcard/swapfile
mkswap /mnt/sdcard/swapfile

Use blkid to get UUID of the sdcard root partition. Configure fstab:

vim /mnt/sdcard/etc/fstab
UUID="c47efd86-d6df-4c76-a4e9-2e8207d28710"     /       ext4    defaults        0 1
/swapfile       swap    swap    defaults 0 0

Create /mnt/sdcard/usr/src/linux/gentoo.its:

/dts-v1/;

/ {
    description = "Chrome OS kernel image with one or more FDT blobs";
    images {
        kernel-1{
            description = "kernel";
            data = /incbin/("arch/arm64/boot/Image");
            type = "kernel_noload";
            arch = "arm64";
            os = "linux";
            compression = "none";
            load = <0>;
            entry = <0>;
        };
        fdt-1{
            description = "rk3399-gru-kevin.dtb";
            data = /incbin/("arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dtb");
            type = "flat_dt";
            arch = "arm64";
            compression = "none";
            hash-1{
                algo = "sha1";
            };
        };
    };
    configurations {
        default = "conf-1";
        conf-1{
            kernel = "kernel-1";
            fdt = "fdt-1";
        };
    };
};

Package and sign the image and write it to boot partition:

lucy /mnt/sdcard/usr/src/linux # mkimage -f gentoo.its gentoo.itb
FIT description: Chrome OS kernel image with one or more FDT blobs
Created:         Fri Feb  2 08:46:34 2024
 Image 0 (kernel-1)
  Description:  kernel
  Created:      Fri Feb  2 08:46:34 2024
  Type:         Kernel Image (no loading done)
  Compression:  uncompressed
  Data Size:    17617408 Bytes = 17204.50 KiB = 16.80 MiB
 Image 1 (fdt-1)
  Description:  rk3399-gru-kevin.dtb
  Created:      Fri Feb  2 08:46:34 2024
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    69134 Bytes = 67.51 KiB = 0.07 MiB
  Architecture: AArch64
  Hash algo:    sha1
  Hash value:   35021c41658ce3f8b86f5fcfe7ca1b0a4fd3ccd2
 Default Configuration: 'conf-1'
 Configuration 0 (conf-1)
  Description:  unavailable
  Kernel:       kernel-1
  FDT:          fdt-1
lucy /mnt/sdcard/usr/src/linux # vim kernel.flags
lucy /mnt/sdcard/usr/src/linux # cat kernel.flags 
console=tty1 root=/dev/mmcblk1p2  rootfstype=ext4 rootwait rw
lucy /mnt/sdcard/usr/src/linux # sync
lucy /mnt/sdcard/usr/src/linux # futility --debug vbutil_kernel --arch arm --version 1 --keyblock /usr/share/vboot/devkeys/kernel.keyblock --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk --bootloader kernel.flags --config kernel.flags --vmlinuz gentoo.itb --pack vmlinuz.signed
DEBUG: run_command: "vbutil_kernel" ...
DEBUG: run_command:   argv[0] = "vbutil_kernel"
DEBUG: run_command:   argv[1] = "--arch"
DEBUG: run_command:   argv[2] = "arm"
DEBUG: run_command:   argv[3] = "--version"
DEBUG: run_command:   argv[4] = "1"
DEBUG: run_command:   argv[5] = "--keyblock"
DEBUG: run_command:   argv[6] = "/usr/share/vboot/devkeys/kernel.keyblock"
DEBUG: run_command:   argv[7] = "--signprivate"
DEBUG: run_command:   argv[8] = "/usr/share/vboot/devkeys/kernel_data_key.vbprivk"
DEBUG: run_command:   argv[9] = "--bootloader"
DEBUG: run_command:   argv[10] = "kernel.flags"
DEBUG: run_command:   argv[11] = "--config"
DEBUG: run_command:   argv[12] = "kernel.flags"
DEBUG: run_command:   argv[13] = "--vmlinuz"
DEBUG: run_command:   argv[14] = "gentoo.itb"
DEBUG: run_command:   argv[15] = "--pack"
DEBUG: run_command:   argv[16] = "vmlinuz.signed"
DEBUG: do_vbutil_kernel: Reading kernel.flags
DEBUG: ReadConfigFile:  config file size=0x38
DEBUG: do_vbutil_kernel: Reading kernel.flags
DEBUG: do_vbutil_kernel:  bootloader file size=0x38
DEBUG: do_vbutil_kernel: Reading gentoo.itb
DEBUG: do_vbutil_kernel:  vmlinuz file size=0x10de6a9
DEBUG: CreateKernelBlob: g_kernel_blob_size  0x10e2000
DEBUG: CreateKernelBlob: g_kernel_size       0x10de6a9 ofs 0x0
DEBUG: CreateKernelBlob: g_config_size       0x1000 ofs 0x10df000
DEBUG: CreateKernelBlob: g_param_size        0x1000 ofs 0x10e0000
DEBUG: CreateKernelBlob: g_bootloader_size   0x1000 ofs 0x10e1000
DEBUG: CreateKernelBlob: g_ondisk_bootloader_addr   0x11e1000
DEBUG: CreateKernelBlob: end of kern_blob at kern_blob+0x10e2000
DEBUG: PickApartVmlinuz:  kernel32_start=0x0
DEBUG: PickApartVmlinuz:  kernel32_size=0x10de6a9
DEBUG: do_vbutil_kernel: kblob_size = 0x10e2000
DEBUG: do_vbutil_kernel: vblock_size = 0x10000
DEBUG: WriteSomeParts: writing vmlinuz.signed with 0x10000, 0x10e2000
lucy /mnt/sdcard/usr/src/linux # dd if=vmlinuz.signed of=/dev/sdc1
34704+0 records in
34704+0 records out
17768448 bytes (18 MB, 17 MiB) copied, 3.95567 s, 4.5 MB/s

Umount everything you can eject the sd card and install it in the chromebook. Use Ctrl+U to boot from external media.

After reboot I noticed it was trying to spawn a serial session so I commented out f0 at the bottom of /etc/inittab.

I also forgot to build the kernel modules…

cd /usr/src/linux
make modules_install
reboot

Then I had wlp1s0 to configure the normal way.

Tweaks

I didn't want my screen to go black in X with a timeout. I have my custom UI but also fluxbox installed. To disable the screen shutting off edit /etc/X11/xorg.conf:

Section "ServerFlags"
     Option "BlankTime" "0"
EndSection

I kept bumping the power button and shutting of the machine due to a default settings in elogind. I edited /etc/elogind/logind.conf:

[Login]
HandlePowerKey=ignore

Conky

-- Conky, a system monitor https://github.com/brndnmtthws/conky
--
-- This configuration file is Lua code. You can write code in here, and it will
-- execute when Conky loads. You can use it to generate your own advanced
-- configurations.
--
-- Try this (remove the `--`):
--
--   print("Loading Conky config")
--
-- For more on Lua, see:
-- https://www.lua.org/pil/contents.html

conky.config = {
    alignment = "top_left",
    use_xft = true,
    font = 'GE Inspira:size=16',
    xftalpha = 0.8,
    text_buffer_size = 2048,
    max_text_width = 0,
    override_utf8_locale = true,
    uppercase = false,
    no_buffers = true,
    short_units = true,
    format_human_readable = true,

    update_interval = 1,
    total_run_times = 0,

    own_window = true,
    own_window_transparent = false,
    own_window_type = 'desktop',
    own_window_hints = 'undecorated,below,sticky,skip_taskbar,skip_pager',
        own_window_argb_visual = true,
        own_window_argb_value = 128,
    background = true,
    use_spacer = 'none',

    double_buffer = true,
    minimum_width = 215, minimum_height = 215,

    draw_shades = false,
    default_shade_color = '#000000',

    draw_outline = false,
    default_outline_color = '#000000',

    default_color = 'FFFFFF',
    color0 = 'FFFFFF',
    color1 = 'FFA300',

    draw_borders = false,
    stippled_borders = 0,
    border_inner_margin = 10,
    border_outer_margin = 0,
    border_width = 1,
    draw_graph_borders = false,--no

    gap_x = 50,
    gap_y = 50,

    imlib_cache_size = 0,
}

conky.text = [[
${color grey}Info:$color ${scroll 32 Conky $conky_version - $sysname $nodename $kernel $machine}
$hr
${color grey}Uptime:$color $uptime
${color grey}Frequency (in MHz):$color $freq
${color grey}Frequency (in GHz):$color $freq_g
${color grey}RAM Usage:$color $mem/$memmax - $memperc% ${membar 4}
${color grey}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar 4}
${color grey}CPU Usage:$color $cpu% ${cpubar 4}
${color grey}Processes:$color $processes  ${color grey}Running:$color $running_processes
$hr
${color grey}File systems:
 / $color${fs_used /}/${fs_size /} ${fs_bar 6 /}
${color grey}Networking:
Up:$color ${upspeed wlp1s0} ${color grey} - Down:$color ${downspeed wlp1s0}
${color grey}Battery:${color} ${battery_percent sbs-9-000b} ${alignr}${battery_bar 8, 250 sbs-9-000b}
$hr
${color grey}Name              PID     CPU%   MEM%
${color lightgrey} ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1}
${color lightgrey} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2}
${color lightgrey} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3}
${color lightgrey} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4}
#
#REFRESH LOCATION & WEATHER INFO CACHE
${execi 600 curl -so ~/.cache/WeatherData 'https://api.openweathermap.org/data/2.5/onecall?units=imperial&lat=46.4855&lon=-88.8940&exclude=minutely,hourly&APPID=a6f8bedf50667be2d3764422a37077d2'}

#
#REFRESH ICON CACHE
${execi 600 sleep 2 && jq -r '.current.weather[0].icon' ~/.cache/WeatherData | xargs printf "http://openweathermap.org/img/wn/%s@2x.png" | xargs curl -so ~/.cache/WeatherNow.png}\
${execi 600 sleep 2 && jq -r '.daily[0].weather[0].icon' ~/.cache/WeatherData | xargs printf "http://openweathermap.org/img/wn/%s@2x.png" | xargs curl -so ~/.cache/Weather0.png}\
${execi 600 sleep 2 && jq -r '.daily[1].weather[0].icon' ~/.cache/WeatherData | xargs printf "http://openweathermap.org/img/wn/%s@2x.png" | xargs curl -so ~/.cache/Weather1.png}\
${execi 600 sleep 2 && jq -r '.daily[2].weather[0].icon' ~/.cache/WeatherData | xargs printf "http://openweathermap.org/img/wn/%s@2x.png" | xargs curl -so ~/.cache/Weather2.png}\
${execi 600 sleep 2 && jq -r '.daily[3].weather[0].icon' ~/.cache/WeatherData | xargs printf "http://openweathermap.org/img/wn/%s@2x.png" | xargs curl -so ~/.cache/Weather3.png}\
${execi 600 sleep 2 && jq -r '.daily[4].weather[0].icon' ~/.cache/WeatherData | xargs printf "http://openweathermap.org/img/wn/%s@2x.png" | xargs curl -so ~/.cache/Weather4.png}
#
#WEATHER NOW
${voffset -40}${color1}Kenton, MI
${color0}${execi 1 jq -r '.current.temp' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}° ${image ~/.cache/WeatherNow.png -s 70x70 -p 160,570}

#WEATHER TODAY                                                                                                            
${color1}Today${goto 100}${color0}${execi 1 jq -r '.daily[0].temp.min' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°/ ${execi 1 jq -r '.daily[0].temp.max' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°${image ~/.cache/Weather0.png -s 30x30 -p 180, 635}
#
#WEATHER +1 DAY
${color1}${execi 1 jq -r '.daily[1].dt' ~/.cache/WeatherData |awk '
{print "@" $1}' |xargs date +%a --date}${goto 100}${color0}${execi 1 jq -r '.daily[1].temp.min' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°/ ${execi 1 jq -r '.daily[1].temp.max' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°${image ~/.cache/Weather1.png -s 30x30 -p 180,658}
#
#WEATHER +2 DAYS
${color1}${execi 1 jq -r '.daily[2].dt' ~/.cache/WeatherData |awk '
{print "@" $1}' |xargs date +%a --date}${goto 100}${color0}${execi 1 jq -r '.daily[2].temp.min' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°/ ${execi 1 jq -r '.daily[2].temp.max' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°${image ~/.cache/Weather2.png -s 30x30 -p 180,685}
#
#WEATHER +3 DAYS
${color1}${execi 1 jq -r '.daily[3].dt' ~/.cache/WeatherData |awk '
{print "@" $1}' |xargs date +%a --date}${goto 100}${color0}${execi 1 jq -r '.daily[3].temp.min' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°/ ${execi 1 jq -r '.daily[3].temp.max' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°${image ~/.cache/Weather3.png -s 30x30 -p 180,710}
#
#WEATHER +4 DAYS
${color1}${execi 1 jq -r '.daily[4].dt' ~/.cache/WeatherData |awk '
{print "@" $1}' |xargs date +%a --date}${goto 100}${color0}${execi 1 jq -r '.daily[4].temp.min' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°/ ${execi 1 jq -r '.daily[4].temp.max' ~/.cache/WeatherData |awk '{print int($1+0.5)}'}°${image ~/.cache/Weather3.png -s 30x30 -p 180,735}
]]
                                                                                                                      

Docker

When attempted to emerge docker I got errors about circular deps with dev-lang/go. I also needed to recompile binutils with gold use flag.

sys-devel/binutils gold

Then I emerged dev-lang/go by itself.

emerge --ask devlang/go

Finally I emerged docker.

emerge --ask app-containers/docker

After that I found I couldn't start a container. I was missing some required kernel CONFIG options.

Refrences