TOC:
- Multiboot Chromium OS with another OSes on Surface devices
- Build the whole Chromium OS by yourself
- Or, use ArnoldTheBat's or CloudReady or any other prebuilt image with modified kernel
- Modify the image to use on Surface devices
- Modify
/usr/sbin/write_gpt.sh
- another modifications to use on Surface devices
- linux-firmware
- Sound on Surface Book 1 may not working by default.
- Sound is not working on Surface 3 by default. Add UCM file:
- Tap to click is not working by default. Edit
/etc/gesture/40-touchpad-cmt.conf
- Disable hardware TPM (valid only if you build your tpm module as external module, not built-in)
- You may also want to disable
mwlwifi
module: - Useful chrome flags
- You may want to add additional fonts
- (optional) if you want to boot this image from USB storage, change STATE partition number
- (optional) change boot parameter if you want
- unmount the loop device
- Modify
- How to install Chromium OS for multiboot?
Basically, follow this guide:
I'll explain what is not described in the above guide.
References (some sources written in Japanese):
- Chromium OS Docs - Chromium OS Developer Guide
- Chromium OSをビルド - Qiita
- Chromium OSでバッテリ駆動時間は伸びるのか? NEC LaVie Zで試す - ビルド実行編
It used up to about 200GB while building stabilize-11895.118.B
# (outside cros_sdk)
# first, checkout to master
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git -b master
# if this is for the first time to sync, `-j8` is recommended
repo sync -j8
# then, checkout to another branch if you want
# you can see the list of branches here:
# https://chromium.googlesource.com/chromiumos/manifest.git
# checkout to release-R76-12239.B
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git -b release-R76-12239.B
# then, sync
repo sync -j16
# checkout to stabilize-12331.B
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git -b stabilize-12331.B
# then, sync
repo sync -j16
# before entering chroot, I recommend to include your Linux distribution's firmware
# Especially, don't forget to add IPTS firmware
#cp -r /lib/firmware/* $HOME/chromiumos/chroot/build/amd64-generic/lib/firmware/
# Or, clone it from kernel.org
cd ~
git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
cp -r linux-firmware/* $HOME/chromiumos/chroot/build/amd64-generic/lib/firmware/
cros_sdk # (inside cros_sdk)
export BOARD=amd64-generic
setup_board --board=${BOARD}
# If you want to modify kernel, do it here
# Follow my guide "How to build a kernel (using `cros_sdk`)"
# https://github.com/kitakar5525/chromeos-kernel-linux-surface#how-to-build-a-kernel-using-cros_sdk
# Build a dev image
FEATURES="noclean" ./build_packages --board=${BOARD} && ./build_image --board=${BOARD} --noenable_rootfs_verification dev
# also, if you want, generate a VM image here
#INFO : To convert it to a VM image, use:
#INFO : ./image_to_vm.sh --from=../build/images/amd64-generic/R77-12342.0.2019_07_14_1634-a1 --board=amd64-generic
#You can start the image with:
#cros_vm --start --image-path /mnt/host/source/src/build/images/amd64-generic/R77-12342.0.2019_07_14_1634-a1/chromiumos_qemu_image.bin
export IMAGE_NAME=chromiumos_image-surface.bin
truncate -s +3g $IMAGE_NAME # increase by 3BG
LOOP_LOCATION=$(losetup -f) # /dev/loopX # get where the image will be mounted
sudo losetup $LOOP_LOCATION -P $IMAGE_NAME
gparted $LOOP_LOCATION # manipulate partitions here
sudo losetup -d $LOOP_LOCATION # unmount that device
References
You may achieve this by editing
(inside cros_sdk) ~/trunk/src/overlays/overlay-amd64-generic/scripts/disk_layout.json
? (not tested)
(outside cros_sdk)
cd ~
export IMAGE_EXPORT_DIR=~/chromiumos-$(basename $(realpath $HOME/chromiumos/src/build/images/amd64-generic/latest))
mkdir $IMAGE_EXPORT_DIR
cp -r $HOME/chromiumos/src/build/images/amd64-generic/latest/* $IMAGE_EXPORT_DIR
Copy module into ROOT-A/lib/modules
and copy vmlinuz to EFI-SYSTEM/syslinux/vmlinuz.A
.
Also, I recommend to include your Linux distribution's firmware.
Especially, don't forget to add IPTS firmware.
cp -r /lib/firmware/* ROOT-A/lib/firmware/
Modify the image before writing to your internal storage. Of course you can do it after writing to your internal storage, but in case you need to reuse this image.
First, mount ROOT-A partition of the image
# first, copy or rename the image name
#cp chromiumos_image.bin chromiumos_image-surface.bin
export IMAGE_NAME=chromiumos_image-surface.bin
LOOP_LOCATION=$(losetup -f) # /dev/loopX # get where the image will be mounted
sudo losetup $LOOP_LOCATION -P $IMAGE_NAME
sleep 1 # for lsblk to recognize the changes
# get location of ROOT-A
LOCATION_ROOT_A=$(lsblk -o NAME,PARTLABEL -r | grep $(basename $LOOP_LOCATION) | grep ROOT-A | cut -d" " -f1) # loopXpY
mkdir -p /tmp/mnt/ROOT-A; sudo mount /dev/$LOCATION_ROOT_A /tmp/mnt/ROOT-A # mount ROOT-A
It seems that, at least to just boot the image, you only need STATE
partition number.
I recommend to use something greater number (explain later how to change actual partition number)
to distinguish Chromium OS pertitions from the other OS partitions.
Another reason is, if I set the number to somewhat greater number,
the image can also be used on another devices without editing write_gpt.sh
.
I personally use 52
, so, the file will look like this:
load_base_vars() {
PARTITION_SIZE_STATE=2147483648
RESERVED_EBS_STATE=0
DATA_SIZE_STATE=2147483648
FORMAT_STATE=
FS_FORMAT_STATE=ext4
FS_OPTIONS_STATE=""
PARTITION_NUM_STATE="52"
PARTITION_SIZE_52=2147483648
RESERVED_EBS_52=0
DATA_SIZE_52=2147483648
FORMAT_52=
FS_FORMAT_52=ext4
FS_OPTIONS_52=""
PARTITION_NUM_52="52"
}
load_partition_vars() {
PARTITION_SIZE_STATE=2147483648
RESERVED_EBS_STATE=0
DATA_SIZE_STATE=2147483648
FORMAT_STATE=
FS_FORMAT_STATE=ext4
FS_OPTIONS_STATE=""
PARTITION_NUM_STATE="52"
PARTITION_SIZE_52=2147483648
RESERVED_EBS_52=0
DATA_SIZE_52=2147483648
FORMAT_52=
FS_FORMAT_52=ext4
FS_OPTIONS_52=""
PARTITION_NUM_52="52"
}
You should want to copy firmware files to the image if you did not before. Otherwise, marvel mwifiex wifi will not work.
# from kernel.org
# git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
# Or, from arch
wget --trust-server-names https://www.archlinux.org/packages/core/any/linux-firmware/download/
mkdir linux-firmware-20190628.70e4394-1-any.pkg
tar -xf linux-firmware-20190628.70e4394-1-any.pkg.tar.xz -C linux-firmware-20190628.70e4394-1-any.pkg
# don't forget to add ipts firmware
cp -r ipts linux-firmware-20190628.70e4394-1-any.pkg/usr/lib/firmware/intel/
sudo cp -r linux-firmware-20190628.70e4394-1-any.pkg/usr/lib/firmware/* /tmp/mnt/ROOT-A/lib/firmware
You may need to comment out the line in a file /etc/modprobe.d/alsa-skl.conf
blacklist snd_hda_intel
git clone --depth 1 https://github.com/plbossart/UCM ucm
sudo cp -r ucm/chtrt5645 /tmp/mnt/ROOT-A/usr/share/alsa/ucm/
Section "InputClass"
Identifier "touchpad"
[...]
# CMT devices potentially process keyboard events
Option "XkbModel" "pc"
Option "XkbLayout" "us"
+
+ # for Surface series touchpad tap to click
+ Option "libinput Tapping Enabled" "1"
+ Option "Tap Minimum Pressure" "0.1"
EndSection
then, sudo restart ui
References:
Make a new file etc/modprobe.d/hw-tpm-blacklist.conf
install tpm_tis /bin/false
blacklist tpm_tis
and add vtpm init conf file:
Make a new file etc/init/_vtpm.conf
start on started boot-services
script
mkdir -p /var/lib/trunks
modprobe tpm_vtpm_proxy
swtpm chardev --vtpm-proxy --tpm2 --tpmstate dir=/var/lib/trunks --ctrl type=tcp,port=10001
swtpm_ioctl --tcp :10001 -i
end script
Install swtpm
wget https://github.com/imperador/chromefy/raw/master/swtpm.tar
tar -xf swtpm.tar
cd swtpm/usr/lib64/
ln -s libswtpm_libtpms.so.0.0.0 libswtpm_libtpms.so.0
ln -s libswtpm_libtpms.so.0 libswtpm_libtpms.so
ln -s libtpms.so.0.6.0 libtpms.so.0
ln -s libtpms.so.0 libtpms.so
ln -s libtpm_unseal.so.1.0.0 libtpm_unseal.so.1
ln -s libtpm_unseal.so.1 libtpm_unseal.so
cd -
sudo cp -r swtpm/usr /tmp/mnt/ROOT-A/
Make a new file etc/modprobe.d/mwlwifi-blacklist.conf
blacklist mwlwifi
Edit etc/chrome_dev.conf
--enable-features=DoubleTapToZoomInTabletMode,DriveFS,PDFAnnotations,VirtualDesks,VizDisplayCompositor,VizHitTest
--force-tablet-mode=touch_view
--top-chrome-touch-ui=disabled
--ash-debug-shortcuts
--show-taps
--pull-to-refresh=1
#--policy-switches-begin
--force-gpu-rasterization
--enable-oop-rasterization
--enable-zero-copy
--ignore-gpu-blacklist
--enable-features=VizDisplayCompositor
--disable-gpu-driver-workarounds
#--policy-switches-end
sudo cp -r /usr/share/fonts/noto* usr/share/fonts/
# Or, get from arch
wget --trust-server-names https://www.archlinux.org/packages/extra/any/noto-fonts/download/
wget --trust-server-names https://www.archlinux.org/packages/extra/any/noto-fonts-emoji/download/
wget --trust-server-names https://www.archlinux.org/packages/extra/any/noto-fonts-cjk/download/
wget --trust-server-names https://www.archlinux.org/packages/community/x86_64/powerline-fonts/download/
wget --trust-server-names https://www.archlinux.org/packages/community/any/awesome-terminal-fonts/download/
mkdir noto-fonts-20190111-2-any.pkg noto-fonts-emoji-20180810-2-any.pkg noto-fonts-cjk-20190409-1-any.pkg
mkdir powerline-fonts-2.7-3-x86_64.pkg awesome-terminal-fonts-1.1.0-2-any.pkg
tar -xf noto-fonts-20190111-2-any.pkg.tar.xz -C noto-fonts-20190111-2-any.pkg
tar -xf noto-fonts-emoji-20180810-2-any.pkg.tar.xz -C noto-fonts-emoji-20180810-2-any.pkg
tar -xf noto-fonts-cjk-20190409-1-any.pkg.tar.xz -C noto-fonts-cjk-20190409-1-any.pkg
tar -xf powerline-fonts-2.7-3-x86_64.pkg.tar.xz -C powerline-fonts-2.7-3-x86_64.pkg
tar -xf awesome-terminal-fonts-1.1.0-2-any.pkg.tar.xz -C awesome-terminal-fonts-1.1.0-2-any.pkg
sudo cp -r noto-fonts-20190111-2-any.pkg/{etc,usr} /tmp/mnt/ROOT-A/
sudo cp -r noto-fonts-emoji-20180810-2-any.pkg/{etc,usr} /tmp/mnt/ROOT-A/
sudo cp -r noto-fonts-cjk-20190409-1-any.pkg/{etc,usr} /tmp/mnt/ROOT-A/
sudo cp -r awesome-terminal-fonts-1.1.0-2-any.pkg/{etc,usr} /tmp/mnt/ROOT-A/
sudo cp -r powerline-fonts-2.7-3-x86_64.pkg/{etc,usr} /tmp/mnt/ROOT-A/
sudo gdisk $LOOP_LOCATION
Command (? for help): x
Command (? for help): t
# assume STATE is currently partition 1, change if not
Partition number (1-12): 1
New partition number (1-128, default 13): 52
Expert command (? for help): w
LOCATION_EFI_SYSTEM=$(lsblk -o NAME,PARTLABEL -r | grep $(basename $LOOP_LOCATION) | grep EFI-SYSTEM | cut -d" " -f1) # loopXpY
mkdir -p /tmp/mnt/EFI-SYSTEM; sudo mount /dev/$LOCATION_EFI_SYSTEM /tmp/mnt/EFI-SYSTEM
sudoedit /tmp/mnt/EFI-SYSTEM/efi/boot/grub.cfg
sudo umount /tmp/mnt/EFI-SYSTEM
sudo umount /tmp/mnt/*
sudo losetup -d $LOOP_LOCATION
First, run gparted and create partitions labeled
- EFI-SYSTEM, vfat or ext4(?), 128MB
- ROOT-A, ext4, 5GB
- STATE, ext4, (size is as you like)
- ROOT-B, ext4, 5GB (If you want to do A/B update)
then, use gdisk
to change partition numbers
# specify your internal storage, check with
# lsblk -o NAME,LABEL,PARTLABEL,SIZE,FSTYPE,MOUNTPOINT,PARTUUID
# in my case, it is nvme0n1
sudo gdisk /dev/nvme0n1
Command (? for help): x
# type "p" to print current partition numbers
Command (? for help): p
# change STATE to 52, in my case, it is currently 8
Expert command (? for help): t
Partition number (1-53): 8
New partition number (1-128, default 54): 52
# change another partitions as you like.
# on Surface Book, I personally use:
# EFI-SYSTEM on 50
# ROOT-A on 51
# ROOT-B on 53
# However, on some other devices (e.g. Surface 3), ROOT partition number can be used only up to `15`.
Mount your EFI-SYSTEM and ROOT-A of your internal storage and your built image
mkdir -p /tmp/mnt/{EFI-SYSTEM,ROOT-A,EFI-SYSTEM-internal,ROOT-A-internal}
# find partition location of image
export IMAGE_NAME=chromiumos_image-surface.bin
LOOP_LOCATION=$(losetup -f) # /dev/loopX
sudo losetup $LOOP_LOCATION -P $IMAGE_NAME
sleep 1 # for lsblk to recognize the changes
LOCATION_ROOT_A=$(lsblk -o NAME,PARTLABEL -r | grep $(basename $LOOP_LOCATION) | grep ROOT-A | cut -d" " -f1) # loopXpY
LOCATION_EFI_SYSTEM=$(lsblk -o NAME,PARTLABEL -r | grep $(basename $LOOP_LOCATION) | grep EFI-SYSTEM | cut -d" " -f1) # loopXpY
# mount image partitions
sudo mount /dev/$LOCATION_EFI_SYSTEM /tmp/mnt/EFI-SYSTEM
sudo mount /dev/$LOCATION_ROOT_A /tmp/mnt/ROOT-A
# mount internal disk partiton
sudo mount /dev/disk/by-label/EFI-SYSTEM /tmp/mnt/EFI-SYSTEM-internal
sudo mount /dev/disk/by-label/ROOT-A /tmp/mnt/ROOT-A-internal
# copy all the contents
sudo cp -a /tmp/mnt/EFI-SYSTEM/* /tmp/mnt/EFI-SYSTEM-internal/
sudo cp -a /tmp/mnt/ROOT-A/* /tmp/mnt/ROOT-A-internal/
# overwrite ROOT-A and ROOT-B PARTUUID of your internal storage on
# /tmp/mnt/EFI-SYSTEM-internal/efi/boot/grub.cfg
# check your PARTUUID by
# lsblk -o NAME,LABEL,PARTUUID
# root=PARTUUID=your-partuuid
# unmount all you mounted
sudo umount /tmp/mnt/*
sudo losetup -d $LOOP_LOCATION
Add boot entry to your bootloader. I personaly use rEFInd. (Sorry I don't know about GRUB.) Maybe your bootloeader will autodetect Chromium OS's bootloader depending on your bootloader setting, though.
menuentry "Chromium OS grub (manual entry)" {
icon /EFI/refind/icons/os_chrome.png
volume EFI-SYSTEM
loader /efi/boot/bootx64.efi
}