diff --git a/CMakeLists.txt b/CMakeLists.txt index 86750a1..a9a5deb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ add_subdirectory(piolib) add_subdirectory(raspinfo) add_subdirectory(rpieepromab) add_subdirectory(rpi-gpu-usage) +add_subdirectory(rpi-ram-authenticity-check) add_subdirectory(vcgencmd) add_subdirectory(vclog) add_subdirectory(vcmailbox) diff --git a/README.md b/README.md index 1da5939..64fcb15 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ A collection of scripts and simple applications secure-boot provisioner. * [rpi-gpu-usage](rpi-gpu-usage/) - A tool for showing the per-process usage of the V3D GPU on Raspberry Pi 4 and 5. +* [rpi-ram-authenticity-check](rpi-ram-authenticity-check/) - A read-only RAM authenticity + check for BCM2712 devices, comparing reported capacity with the factory configuration. * [splashasm](splashasm/) - A tool for writing spi & i2c dumps for fast display at boot * [vcgencmd](vcgencmd/) - A tool to send commands to the VideoCore firmware and display the results. diff --git a/raspinfo/README.md b/raspinfo/README.md index 2c9eb35..143d7f7 100644 --- a/raspinfo/README.md +++ b/raspinfo/README.md @@ -1,2 +1,7 @@ # raspinfo Short script to dump information about the Pi. Use it for annotating bug reports. + +On BCM2712 devices, includes the output of +[`rpi-ram-authenticity-check`](../rpi-ram-authenticity-check/) when installed. +RAM mismatch warnings and unavailable checks are recorded in `raspinfo.txt` +without stopping the rest of the report. diff --git a/raspinfo/raspinfo b/raspinfo/raspinfo index d3cee29..99b1965 100755 --- a/raspinfo/raspinfo +++ b/raspinfo/raspinfo @@ -235,6 +235,19 @@ cat /proc/cpuinfo | tail -3 echo "Throttled flag : "`vcgencmd get_throttled` +if grep -q bcm2712 /proc/device-tree/compatible 2>/dev/null; then + echo + echo "RAM authenticity" + echo "----------------" + echo + if command -v rpi-ram-authenticity-check > /dev/null; then + rpi-ram-authenticity-check 2>&1 || : + else + echo "rpi-ram-authenticity-check not found" + fi + echo +fi + echo "Camera Information" echo "------------------" diff --git a/rpi-ram-authenticity-check/CMakeLists.txt b/rpi-ram-authenticity-check/CMakeLists.txt new file mode 100644 index 0000000..99fc7e8 --- /dev/null +++ b/rpi-ram-authenticity-check/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10...3.27) + +include(GNUInstallDirs) + +project(rpi-ram-authenticity-check) + +install(PROGRAMS rpi-ram-authenticity-check DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/rpi-ram-authenticity-check/README.md b/rpi-ram-authenticity-check/README.md new file mode 100644 index 0000000..202fb3e --- /dev/null +++ b/rpi-ram-authenticity-check/README.md @@ -0,0 +1,28 @@ +# rpi-ram-authenticity-check + +Read-only RAM authenticity check for BCM2712 devices (the Pi 5 family). +Compares the RAM capacity in the running board revision (from device tree or +`/proc/cpuinfo`) with the factory revision in OTP row 32. + +Run `rpi-ram-authenticity-check` after installing utils, or directly from this +repository: + +```sh +./rpi-ram-authenticity-check/rpi-ram-authenticity-check +``` + +Requires `vcgencmd` and access to `/dev/vcio`; run with `sudo` if access is denied. +Use `--help` for usage information. + +A mismatch warns of possible RAM tampering or replacement and advises contacting +the seller to arrange a return. Matching capacity is reported as "RAM appears +authentic", but cannot detect a replacement with the same capacity. + +Exit status: + +* `0`: capacity matches. +* `1`: capacity differs. +* `2`: unable to check, including unsupported hardware or missing/invalid data. + +When installed, the checker is also called by `raspinfo` on BCM2712 devices. +Its output, including warnings, is included in `raspinfo.txt`. diff --git a/rpi-ram-authenticity-check/rpi-ram-authenticity-check b/rpi-ram-authenticity-check/rpi-ram-authenticity-check new file mode 100755 index 0000000..ead65bb --- /dev/null +++ b/rpi-ram-authenticity-check/rpi-ram-authenticity-check @@ -0,0 +1,76 @@ +#!/bin/sh + +# Compare BCM2712's reported RAM capacity with its factory revision in OTP. +set -ef + +usage() { + cat <&2 + exit 2 +} + +ramSizeFromRevision() { + case "$1" in + ''|*[!0-9a-fA-F]*) return 1 ;; + esac + [ "${#1}" -le 8 ] || return 1 + # Require a new-style BCM2712 revision before interpreting its RAM field. + [ $(((0x$1 >> 23) & 1)) -eq 1 ] && + [ $(((0x$1 >> 12) & 15)) -eq 4 ] || return 1 + ram_code=$(((0x$1 >> 20) & 7)) + # Code 7 means "Other", not 32 GiB. + [ "${ram_code}" -lt 7 ] || return 1 + echo "$((256 << ram_code))" +} + +if [ "$#" -ne 0 ]; then + if [ "$#" -eq 1 ] && { [ "$1" = -h ] || [ "$1" = --help ]; }; then + usage + exit 0 + fi + usage >&2 + exit 2 +fi + +# Use the same running revision sources as rpi-eeprom-update. Do not fall +# back to OTP here: comparing the factory value with itself would miss changes. +dt_revision=/sys/firmware/devicetree/base/system/linux,revision +if [ -r "${dt_revision}" ]; then + [ "$(wc -c < "${dt_revision}")" -eq 4 ] || die "Invalid device-tree board revision." + board_revision=$(od -v -An -t x1 "${dt_revision}" | tr -d ' \n') +elif [ -r /proc/cpuinfo ]; then + board_revision=$(sed -n '/^Revision/s/^.*: \(.*\)/\1/p' /proc/cpuinfo) +else + die "No running board revision found." +fi +reported_mib=$(ramSizeFromRevision "${board_revision}") || + die "The running board revision must describe a BCM2712 device with a known RAM capacity." + +command -v vcgencmd > /dev/null || die "vcgencmd is required to read the factory RAM capacity." +otp_dump=$(vcgencmd otp_dump) || die "Failed to read OTP; check access to /dev/vcio." +# Row 32 is the BCM2712 factory revision; BCM2711 uses row 30. +factory_revision=$(printf '%s\n' "${otp_dump}" | sed -n 's/^32:\([0-9a-fA-F]\{8\}\)$/\1/p') +factory_mib=$(ramSizeFromRevision "${factory_revision}") || + die "OTP row 32 does not contain a valid BCM2712 revision with a known RAM capacity." + +echo "Factory RAM: ${factory_mib} MiB; reported RAM: ${reported_mib} MiB." +if [ "${factory_mib}" -eq "${reported_mib}" ]; then + echo "RAM appears authentic: capacity matches the factory configuration." + exit 0 +fi + +echo "WARNING: RAM capacity mismatch detected: possible RAM tampering or replacement." >&2 +echo "Contact the seller to arrange a return." >&2 +exit 1