#!/bin/bash
#
#  aucode-tool
#  Copyright (c) Aug 2020 by Terry Neve <terryn94@gmail.com>
#
#  Program to generate early microcode file for AMD processors
#  File name can be passed on command line otherwise will be chosen
#  using CPU family read from /proc/cpuinfo.

INITRD=/boot/early_ucode.img
DSTDIR=kernel/x86/microcode
TMPDIR=/tmp/initrd
UCODE_FILE=$1

# check we are running as root
if (($EUID != 0)); then
    echo "ERROR: $0 must be run as root"
    exit 1
fi

# check it is an AMD processor
if ! grep -F -m 1 "vendor_id" /proc/cpuinfo | cut -d: -f2 | grep AuthenticAMD; then
    echo "ERROR: Processor is not an AMD CPU"
    exit 1
fi

if [ -z $UCODE_FILE ]; then
    # lookup CPU family and select firmware blob
    CPU_FAMILY=$(grep -F -m 1 "cpu family" /proc/cpuinfo | cut -d: -f2 | sed 's/^ //')
    echo "CPU family: $CPU_FAMILY"

    case "$CPU_FAMILY" in
        16 | 17 | 18 | 20)
            UCODE_FILE="microcode_amd.bin"
            ;;
        21)
            UCODE_FILE="microcode_amd_fam15h.bin"
            ;;    
        22)
            UCODE_FILE="microcode_amd_fam16h.bin"
            ;;
        23)
            UCODE_FILE="microcode_amd_fam17h.bin"
            ;;
        25)
            UCODE_FILE="microcode_amd_fam19h.bin"
            ;;
        *)
            echo "ERROR: Unrecognized CPU family or microcode not supported"
            exit 1
            ;;
    esac
fi
echo "Microcode file: $UCODE_FILE"
    
# Generate early_ucode file
rm -rf $TMPDIR
mkdir $TMPDIR
cd $TMPDIR
mkdir -p $DSTDIR

if [ -f /lib/firmware/amd-ucode/$UCODE_FILE ]; then
        cp -p /lib/firmware/amd-ucode/$UCODE_FILE $DSTDIR/AuthenticAMD.bin
        echo "Writing early_ucode image to $INITRD"
        find . | cpio -o -H newc >$INITRD
fi
rm -rf $TMPDIR
