Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f8b2ffc
payloads/external/Makefile.mk: remove duplicated options
SergiiDmytruk Jun 2, 2026
7a3ccc9
drivers/efi,ec/dasharo,payloads/edk: introduce CONFIG_DRIVERS_EFI_EC_…
SergiiDmytruk Jun 2, 2026
e886fa5
drivers/efi,coreboot_tables.h: publish Dasharo EC information
SergiiDmytruk Jun 3, 2026
5509a28
payloads/edk2/Kconfig.dasharo: bump EDK for EC capsules
SergiiDmytruk Jun 3, 2026
6c3afd6
capsule.sh: extract $v2_capsule in make_subcommand()
SergiiDmytruk Jun 8, 2026
1bdf809
capsule.sh: clean up handling of drivers by make subcommand
SergiiDmytruk Jun 8, 2026
4960119
capsule.sh: extract build_capsule() out of make_subcommand()
SergiiDmytruk Jun 8, 2026
900fa85
capsule.sh: pass certs to build_capsule() as well
SergiiDmytruk Jun 8, 2026
2e33b63
capsule.sh: add -e option to "make" for EC ROMs
SergiiDmytruk Jun 9, 2026
e13e27b
capsule.sh: improve help of make command's -b flag
SergiiDmytruk Jun 9, 2026
70cbba9
capsule.sh: add -y flag to make command
SergiiDmytruk Jun 9, 2026
3ab4d62
capsule.sh: add -c flag to make command
SergiiDmytruk Jun 9, 2026
69d10c7
payloads/edk2: pass CONFIG_EC_DASHARO_EC_FLASH_SIZE in a PCD
SergiiDmytruk Jun 14, 2026
d0cb08d
ec/dasharo: fix return value of ec_spi_image_write()
SergiiDmytruk Jun 14, 2026
ae78a66
ec/dasharo: add missing sector erasure verification
SergiiDmytruk Jun 14, 2026
f808b2d
ec/dasharo: don't pass less than 2 bytes to CMD_SPI
SergiiDmytruk Jun 14, 2026
7b91c7c
ec/dasharo: update three log messages
SergiiDmytruk Jun 14, 2026
39e125f
drivers/efi/capsules.c: build accurate RAM map
SergiiDmytruk Jun 14, 2026
26314b8
src/soc/intel/common/block/crashlog: Add driver for PMC SRAM device
mkopec Aug 20, 2026
08925e4
src/soc/intel/alderlake/crashlog.c: Harden against unreachable BAR
mkopec Aug 20, 2026
95357c7
.github/workflows/build.yml: build any dasharo[-*] branch and PRs to it
SergiiDmytruk Jun 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ name: Dasharo
on:
pull_request:
branches:
- dasharo-25.12
- dasharo
- dasharo-20*
push:
branches:
- dasharo-25.12
- dasharo
- dasharo-20*
tags:
- '*'

Expand Down
274 changes: 180 additions & 94 deletions capsule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ function print_usage() {
echo ' -t root-certificate-file'
echo ' -o subroot-certificate-file'
echo ' -s signing-certificate-file'
echo ' -b (the flag adds battery check DXE into the capsule)'
echo ' [-b] (include battery check DXE in the capsule)'
echo ' [-y] (overwrite destination without prompting)'
echo ' [-e ec-rom-file] (make an EC firmware capsule)'
echo ' [-c cap-file] (destination file name, generated if omitted)'
echo ' resign resign an existing capsule with a different key'
echo ' -t root-certificate-file'
echo ' -o subroot-certificate-file'
Expand Down Expand Up @@ -229,89 +232,35 @@ function check_generate_capsule() {
fi
}

function make_subcommand() {
if [ ! -f .config ]; then
die "no '.config' file in current directory"
fi
if [ ! -f build/coreboot.rom ]; then
die "no 'build/coreboot.rom'; the firmware wasn't built?"
fi
if [ ! build/coreboot.rom -nt .config ]; then
die "'build/coreboot.rom' is not newer than .config'; need a re-build?"
fi

check_generate_capsule

source_coreboot_config
require_capsule_support

# Option names match terminology of GenerateCapsule which conveniently start
# with different letters:
# * t - trusted
# * o - other
# * s - signer

local root_cert sub_cert sign_cert include_battery_check
while getopts "t:o:s:b" OPTION; do
case $OPTION in
t) root_cert="$OPTARG" ;;
o) sub_cert="$OPTARG" ;;
s) sign_cert="$OPTARG" ;;
b) include_battery_check=1 ;;
*) exit 1 ;;
esac
done

check_cert root "$root_cert"
check_cert sub "$sub_cert"
check_cert sign "$sign_cert"
# This function assumes .config has been sourced.
function build_capsule() {
local payload=$1
local guid=$2
local version=$3
local lsv=$4
local -n drivers=$5
local -n certs=$6
local cap_file=$7

local cap_file=${CONFIG_MAINBOARD_DIR//[\/-]/_}
if [[ ${CONFIG_MAINBOARD_PART_NUMBER} =~ DDR4 ]]; then
cap_file+=_ddr4
fi
cap_file+=_${CONFIG_LOCALVERSION}
cap_file+=.cap

local cap_flags="--capflag PersistAcrossReset"
local cap_flags=( --capflag PersistAcrossReset )
# Capsules on AMD boards do not survive resets
if [ "$CONFIG_EDK2_CAPSULE_DOES_NOT_SURVIVE_RESET" == y ]; then
cap_flags=""
fi

if [ -e "$cap_file" ]; then
confirm "Overwrite already existing '$cap_file'?"
if [ "$CONFIG_EDK2_CAPSULE_DOES_NOT_SURVIVE_RESET" = y ]; then
cap_flags=()
fi

local build_type
if [ "$CONFIG_EDK2_RELEASE" = y ]; then
build_type=RELEASE
else
build_type=DEBUG
local v2_capsule=no
if [ "${CONFIG_EDK2_CAPSULES_V2:-n}${CONFIG_EDK2_CAPSULES_V2_TRANSITION:-n}" = yn ]; then
v2_capsule=yes
fi

local json_file
json_file=$(mktemp --tmpdir --suffix -cap.json XXXXXXXX)
trap "$(printf 'rm -f -- %q %q' "$json_file" "$cap_file.inner")" EXIT

cat > "$json_file" << EOF
{
"EmbeddedDrivers": [
EOF

# Ensure the charger check driver module is first
if [ "$include_battery_check" = 1 ]; then
cat >> "$json_file" << EOF
{
"Driver": "${edk_workspace}/Build/DasharoPayloadPkgX64/${build_type}_GCC/X64/CapsuleChargerCheckDxe.efi"
},
EOF
fi

local opt_root_cert=$root_cert
local opt_sub_cert=$sub_cert
local opt_sign_cert=$sign_cert
if [ "${CONFIG_EDK2_CAPSULES_V2:-n}${CONFIG_EDK2_CAPSULES_V2_TRANSITION:-n}" = yn ]; then
local opt_root_cert=${certs[root]}
local opt_sub_cert=${certs[sub]}
local opt_sign_cert=${certs[sign]}
if [ "$v2_capsule" = yes ]; then
# The inner capsule is always signed with the test key. Not signing it
# at all doesn't work because FmpDxe doesn't accept unsigned payloads at
# least due to Image->AuthInfo.Hdr.wRevision check in
Expand All @@ -321,20 +270,17 @@ EOF
opt_sign_cert=${edk_basetools}/Source/Python/Pkcs7Sign/TestCert.pem
fi

cat >> "$json_file" << EOF
{
"Driver": "${edk_workspace}/Build/DasharoPayloadPkgX64/${build_type}_GCC/X64/CapsuleSplashDxe.efi"
},
{
"Driver": "${edk_workspace}/Build/DasharoPayloadPkgX64/${build_type}_GCC/X64/FmpDxe.efi"
}
cat > "$json_file" << EOF
{
"EmbeddedDrivers": [
$(printf ' { "Driver": "%s" },\n' "${drivers[@]}" | sed '$s/,$//')
],
"Payloads": [
{
"Payload": "build/coreboot.rom",
"Guid": "${CONFIG_DRIVERS_EFI_MAIN_FW_GUID}",
"FwVersion": "${CONFIG_DRIVERS_EFI_MAIN_FW_VERSION}",
"LowestSupportedVersion": "${CONFIG_DRIVERS_EFI_MAIN_FW_LSV}",
"Payload": "${payload}",
"Guid": "${guid}",
"FwVersion": "${version}",
"LowestSupportedVersion": "${lsv}",

"OpenSslSignerPrivateCertFile": "${opt_sign_cert}",
"OpenSslOtherPublicCertFile": "${opt_sub_cert}",
Expand All @@ -344,29 +290,30 @@ EOF
}
EOF

if [ "${CONFIG_EDK2_CAPSULES_V2:-n}${CONFIG_EDK2_CAPSULES_V2_TRANSITION:-n}" = yn ]; then
if [ "$v2_capsule" = yes ]; then
# The capsule created above is the inner capsule. Make it and then
# update JSON file to point at it as a payload.
if ! "$generate_capsule" --encode \
$cap_flags \
"${cap_flags[@]}" \
--json-file "$json_file" \
--output "$cap_file.inner"; then
die "GenerateCapsule failed"
fi

# The outer capsule is signed with the key passed by the user.
cat > "$json_file" << EOF
{
"EmbeddedDrivers": [],
"Payloads": [
{
"Payload": "$cap_file.inner",
"Guid": "${CONFIG_DRIVERS_EFI_MAIN_FW_GUID}",
"FwVersion": "${CONFIG_DRIVERS_EFI_MAIN_FW_VERSION}",
"LowestSupportedVersion": "${CONFIG_DRIVERS_EFI_MAIN_FW_LSV}",
"Guid": "${guid}",
"FwVersion": "${version}",
"LowestSupportedVersion": "${lsv}",

"OpenSslSignerPrivateCertFile": "${sign_cert}",
"OpenSslOtherPublicCertFile": "${sub_cert}",
"OpenSslTrustedPublicCertFile": "${root_cert}"
"OpenSslSignerPrivateCertFile": "${certs[sign]}",
"OpenSslOtherPublicCertFile": "${certs[sub]}",
"OpenSslTrustedPublicCertFile": "${certs[root]}"
}
]
}
Expand All @@ -376,11 +323,150 @@ EOF
# Linux doesn't support InitiateReset flag, omitting it to rely on manual
# warm reset
if ! "$generate_capsule" --encode \
$cap_flags \
"${cap_flags[@]}" \
--json-file "$json_file" \
--output "$cap_file"; then
die "GenerateCapsule failed"
fi
}

# Prints version of an EC ROM derived from the file or dies.
# The implementation of version conversion must be kept in sync with
# parse_ec_version() in src/drivers/efi/info.c
function extract_ec_version() {
local ec_rom_file=$1

local ver
ver=$(strings "$ec_rom_file" | \
sed -n '/^76EC_VERSION/s/.*=\([0-9]\{4\}\(-[0-9][0-9]\)\{2\}\).*/\1/p' | \
head -1)

if [ -z "$ver" ]; then
die "Failed to extract 76EC_VERSION from '$ec_rom_file'"
fi

local y=${ver::4}
local m=${ver:5:2}
local d=${ver:8:2}

echo $(( ((10#$y & 0xffff) << 16) | ((10#$m & 0xff) << 8) | (10#$d & 0xff) ))
}

function make_subcommand() {
if [ ! -f .config ]; then
die "no '.config' file in current directory"
fi
if [ ! -f build/coreboot.rom ]; then
die "no 'build/coreboot.rom'; the firmware wasn't built?"
fi
if [ ! build/coreboot.rom -nt .config ]; then
die "'build/coreboot.rom' is not newer than .config'; need a re-build?"
fi

check_generate_capsule

source_coreboot_config
require_capsule_support

# Option names for key files match terminology of GenerateCapsule which,
# conveniently, has words starting with different letters:
# * t - trusted
# * o - other
# * s - signer

local -A cap_certs
local include_battery_check overwrite_output ec_rom_file cap_file
while getopts "t:o:s:be:yc:" OPTION; do
case $OPTION in
t) cap_certs[root]="$OPTARG" ;;
o) cap_certs[sub]="$OPTARG" ;;
s) cap_certs[sign]="$OPTARG" ;;
b) include_battery_check=1 ;;
y) overwrite_output=1 ;;
e) ec_rom_file="$OPTARG" ;;
c) cap_file="$OPTARG" ;;
*) exit 1 ;;
esac
done

check_cert root "${cap_certs[root]}"
check_cert sub "${cap_certs[sub]}"
check_cert sign "${cap_certs[sign]}"

# Assuming a coreboot capsule at first.
local rom_file=build/coreboot.rom
local guid=$CONFIG_DRIVERS_EFI_MAIN_FW_GUID
local splash_guid=E1CBE3CC-3D32-44CF-8DB9-2A78BA16F2F6
local version=$CONFIG_DRIVERS_EFI_MAIN_FW_VERSION
local lsv=$CONFIG_DRIVERS_EFI_MAIN_FW_LSV

if [ -n "$ec_rom_file" ]; then
if [ -z "$CONFIG_DRIVERS_EFI_EC_FW_GUID" ]; then
die '-e is passed but CONFIG_DRIVERS_EFI_EC_FW_GUID is empty'
fi

assert_file_exists "$ec_rom_file"

local ec_rom_version
ec_rom_version=$(extract_ec_version "$ec_rom_file")

local size
size=$(stat --printf %s "$ec_rom_file")
if [ "$size" -ne $(( $CONFIG_DRIVERS_EFI_EC_FW_SIZE )) ]; then
die "$(printf "'%s' is 0x%x bytes in size instead of 0x%x" \
"$ec_rom_file" \
"$size" \
"$CONFIG_DRIVERS_EFI_EC_FW_SIZE")"
fi

rom_file=$ec_rom_file
guid=$CONFIG_DRIVERS_EFI_EC_FW_GUID
splash_guid=8C675702-A60D-462C-B950-12F00FFDFFF3
version=$ec_rom_version
lsv=$CONFIG_DRIVERS_EFI_EC_FW_LSV
fi

if [ -z "$cap_file" ]; then
cap_file=${CONFIG_MAINBOARD_DIR//[\/-]/_}
if [[ ${CONFIG_MAINBOARD_PART_NUMBER} =~ DDR4 ]]; then
cap_file+=_ddr4
fi
if [ -n "$ec_rom_file" ]; then
cap_file+=_ec
fi
cap_file+=_${CONFIG_LOCALVERSION}
cap_file+=.cap
fi

if [ "$overwrite_output" != 1 ] && [ -e "$cap_file" ]; then
confirm "Overwrite already existing '$cap_file'?"
fi

local build_type
if [ "$CONFIG_EDK2_RELEASE" = y ]; then
build_type=RELEASE
else
build_type=DEBUG
fi

local build_dir=${edk_workspace}/Build/DasharoPayloadPkgX64/${build_type}_GCC/X64

# Ensure the charger check driver module is first
local embedded_drivers=()
if [ "$include_battery_check" = 1 ]; then
embedded_drivers+=( "${build_dir}/CapsuleChargerCheckDxe.efi" )
fi
embedded_drivers+=(
# Can't use the same GUID more than once and can't easily derive it
# either, so CapsuleSplashDxe has hard-coded GUIDs for main/EC firmware
# and one of them is selected above.
"${build_dir}/DasharoPayloadPkg/CapsuleSplashDxe/${splash_guid}/OUTPUT/CapsuleSplashDxe.efi"
"${build_dir}/FmpDevicePkg/FmpDxe/${guid}/OUTPUT/FmpDxe.efi"
)

build_capsule "$rom_file" "$guid" "$version" "$lsv" \
embedded_drivers cap_certs \
"$cap_file"

echo "Created the capsule at '$cap_file'"
}
Expand Down
6 changes: 3 additions & 3 deletions payloads/external/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,6 @@ $(obj)/UEFIPAYLOAD.fd: $(DOTCONFIG) $(IPXE_EFI)
CONFIG_CPU_MAX_TEMPERATURE=$(CONFIG_CPU_MAX_TEMPERATURE) \
CONFIG_EDK2_USE_LAPTOP_LID_LIB=$(CONFIG_EDK2_USE_LAPTOP_LID_LIB) \
CONFIG_EDK2_USE_UEFIVAR_BACKED_TPM_PPI=$(CONFIG_EDK2_USE_UEFIVAR_BACKED_TPM_PPI) \
CONFIG_DRIVERS_EFI_UPDATE_CAPSULES=$(CONFIG_DRIVERS_EFI_UPDATE_CAPSULES) \
CONFIG_DRIVERS_EFI_MAIN_FW_GUID=$(CONFIG_DRIVERS_EFI_MAIN_FW_GUID) \
CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=$(CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE) \
CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=$(CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE) \
CONFIG_EDK2_USB_PORT_POWER_OPTION=$(CONFIG_EDK2_USB_PORT_POWER_OPTION) \
Expand All @@ -310,7 +308,9 @@ $(obj)/UEFIPAYLOAD.fd: $(DOTCONFIG) $(IPXE_EFI)
CONFIG_VGA_BIOS_FILE=$(CONFIG_VGA_BIOS_FILE) \
CONFIG_BOOTSPLASH_REGION_LOGO_FILE=$(CONFIG_BOOTSPLASH_REGION_LOGO_FILE) \
CONFIG_EDK2_AP_INIT_TIMEOUT=$(call int-multiply, $(CONFIG_MAX_CPUS) 100000) \
CONFIG_EDK2_MAX_CPUS=$(CONFIG_MAX_CPUS)
CONFIG_EDK2_MAX_CPUS=$(CONFIG_MAX_CPUS) \
CONFIG_DRIVERS_EFI_EC_FW_GUID=$(CONFIG_DRIVERS_EFI_EC_FW_GUID) \
CONFIG_EC_DASHARO_EC_FLASH_SIZE=$(CONFIG_EC_DASHARO_EC_FLASH_SIZE)

$(obj)/ShimmedUniversalPayload.elf: $(DOTCONFIG)
$(MAKE) -C payloads/external/edk2 UniversalPayload \
Expand Down
2 changes: 1 addition & 1 deletion payloads/external/edk2/Kconfig.dasharo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ config EDK2_REPOSITORY
default "https://github.com/Dasharo/edk2"

config EDK2_TAG_OR_REV
default "61ce35c29bb384240028d4319755b5759affbbe1"
default "00a34ad6795e6638462c2787254d689c15992a6b"

config EDK2_SYSTEM76_EC_LOGGING
bool "Enable edk2 logging to System76 EC"
Expand Down
4 changes: 4 additions & 0 deletions payloads/external/edk2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ endif
ifeq ($(CONFIG_DRIVERS_EFI_UPDATE_CAPSULES),y)
BUILD_STR += -D CAPSULE_SUPPORT=TRUE
BUILD_STR += -D CAPSULE_MAIN_FW_GUID=$(CONFIG_DRIVERS_EFI_MAIN_FW_GUID)
BUILD_STR += -D CAPSULE_EC_FW_GUID=$(CONFIG_DRIVERS_EFI_EC_FW_GUID)
ifneq ($(CONFIG_EC_DASHARO_EC_FLASH_SIZE),)
BUILD_STR += --pcd gDasharoPayloadPkgTokenSpaceGuid.PcdEcFlashSize=$(CONFIG_EC_DASHARO_EC_FLASH_SIZE)
endif
ifeq ($(CONFIG_EDK2_CAPSULE_DOES_NOT_SURVIVE_RESET),y)
BUILD_STR += --pcd gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset=FALSE
BUILD_STR += --pcd gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport=TRUE
Expand Down
Loading
Loading