As my old laptop ages, the condition of it keeps degrading (broken chassis/hinge, wear-out battery, nonfunctional numpad, etc.). Recently I switched to a new laptop - yoga 14s AMD version.

AMD YES

AMD Ryzen CPUs are much more powerful than Intel’s. With this low voltage mobile CPU Ryzen 4800U, it can even beat Intel’s high-end desktop CPUs.

Not to mention AMD’s CPUs are affected by less vulnerabilities as well. Finally I can drop mitigations=off from the kernel command line.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ grep . /sys/devices/system/cpu/vulnerabilities/*
/sys/devices/system/cpu/vulnerabilities/itlb_multihit:Not affected
/sys/devices/system/cpu/vulnerabilities/l1tf:Not affected
/sys/devices/system/cpu/vulnerabilities/mds:Not affected
/sys/devices/system/cpu/vulnerabilities/meltdown:Not affected
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass:Mitigation: Speculative Store Bypass disabled via prctl and seccomp
/sys/devices/system/cpu/vulnerabilities/spectre_v1:Mitigation: usercopy/swapgs barriers and __user pointer sanitization
/sys/devices/system/cpu/vulnerabilities/spectre_v2:Mitigation: Full AMD retpoline, IBPB: conditional, IBRS_FW, STIBP: conditional, RSB filling
/sys/devices/system/cpu/vulnerabilities/srbds:Not affected
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort:Not affected

Update BIOS firmware from Linux

⚠️ WARNING: If there is an error during the BIOS update process, it may cause unrecoverable consequences. If you are worried about these consequences, stop reading and consult the technicians in Lenovo’s service center. If you understand and accept the risks, and want to do it yourself (DIY), continue the read.

Updating BIOS firmware from Linux could be tricky. It’s better to update the BIOS firmware from Windows first, then erase Windows and install Linux.

Yoga 14s AMD Ryzen doesn’t have firmware on Linux Vendor Firmware Service, and the updater is released as an executable instead of a bios update iso image (link to Lenovo’s site). I have to follow https://wiki.archlinux.org/index.php/Flashing_BIOS_from_Linux#Using_a_windows_PE. The tricky parts are:

  • The laptop only boots from UEFI. (So the FreeDOS based methods doesn’t work.)
  • The BIOS updater has secure update enabled, and can not mount the ESP partition.

To fix these problems, I have to disable the secure update function for the BIOS updater, and make an UEFI bootable Windows PE image.

Firstly, install the needed tools

1
$ sudo pacman -S innoextract wimlib cdrtools

Download the BIOS updater executable from Lenovo’s site. Use innoextract to extract the BIOS updater.

1
2
3
4
5
$ innoextract BIOS-DMCN32WW.exe
Extracting "Lenovo BIOS Update Utility" - setup data version 5.5.7 (unicode)
 - "codeGetExtractPath/Win64.bat"
 - "codeGetExtractPath/WIN64.exe"
Done.

The extracted files are in codeGetExtractPath folder. Inside it there is an executable WIN64.exe. Extract it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ cd codeGetExtractPath
$ 7z x WIN64.exe -oupdater

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,16 CPUs AMD Ryzen 7 4800U with Radeon Graphics          (860F01),ASM,AES-NI)

Scanning the drive for archives:
1 file, 6429646 bytes (6279 KiB)

Extracting archive: WIN64.exe
WARNING:
WIN64.exe
Can not open the file as [PE] archive
The file is open as [7z] archive

--
Path = WIN64.exe
Open WARNING: Can not open the file as [PE] archive
Type = 7z
Offset = 590965
Physical Size = 5838681
Headers Size = 508
Method = LZMA:24 BCJ
Solid = +
Blocks = 2

Everything is Ok

Archives with Warnings: 1
Files: 15
Size:       23024732
Compressed: 6429646

Edit the updater/platform.ini file, find and change viaESP=1 to viaESP=0.

1
2
[SecureUpdate]
viaESP=0

Follow https://wiki.archlinux.org/index.php/Windows_PE#Creating_a_bootable_Windows_PE_image to create the Windows PE image using mkwinpeimg, use the --overlay option to include contents in updater folder to the image.

1
2
$ mkwinpeimg --iso --windows-dir=/media/winimg --start-script=start.cmd winpe.iso --overlay codeGetExtractPath/updater

Then make the image UEFI bootable by following https://wiki.archlinux.org/index.php/Windows_PE#Prepare_a_bootable_Windows_PE_USB_key_for_UEFI_systems.

Reboot, hold F12 key, choose to boot from the Windows PE. The Windows command line will pop up. Go to the root folder of Windows PE, and run the actual updater H2OFFT-Wx64.exe, the BIOS updater will start and do it’s job.

1
2
$ cd X:\
$ H2OFFT-Wx64.exe

Enabling S3 suspend-to-RAM

For some laptop models, there is an option in BIOS to switch the sleep mode between Windows and Linux.

To check whether S3 is recognized and usable by Linux, run

1
2
$ dmesg | grep -i "acpi: (supports"
[    0.358340] ACPI: (supports S0 S4 S5)

For BIOS version DMCN32WW, S3 doesn’t appear in the output, and there is no option to switch the sleep mode, which means I have to modify the DSDT table to enable S3 suspend.

Firstly, install the needed tools.

1
$ sudo pacman -S acpica cpio

Dump the DSDT table.

1
$ cat /sys/firmware/acpi/tables/DSDT > dsdt.aml

De-compile the dumped table.

1
$ iasl -d dsdt.aml

Get and apply the patch.

1
2
$ curl -O https://gist.githubusercontent.com/zurohki/4b859668c901e6ba13e8187a0d5d734c/raw/a04e217f273630cfae8ab3aa82002e99b9b039d5/dsdt.patch
$ patch -p1 < dsdt.patch

Recompile the patched DSDT source.

1
$ iasl -ve -tc dsdt.dsl

Create an CPIO archive.

1
2
3
$ mkdir -p kernel/firmware/acpi
$ cp dsdt.aml kernel/firmware/acpi
$ find kernel | cpio -H newc --create > acpi_override

Copy the CPIO archive to /boot.

1
$ sudo cp acpi_override /boot

Edit the boot loader’s configuration file, add the initrd for CPIO archive initrd /acpi_override and add mem_sleep_default=deep to kernel’s command line arguments.

1
2
3
4
5
6
7
$ cat /boot/loader/entries/arch_zen.conf
title Arch Linux - zen kernel
linux /vmlinuz-linux-zen
initrd /amd-ucode.img
initrd /acpi_override
initrd /initramfs-linux-zen.img
options root=PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw quiet mem_sleep_default=deep

Reboot, and check the S3 state again.

1
2
3
4
$ dmesg | grep -i "acpi: (supports"
[    0.358340] ACPI: (supports S0 S3 S4 S5)
$ cat /sys/power/mem_sleep
s2idle [deep]

The S3 suspend is recognized and used.

References