From 3a2310e05c971e3b46e9e91886bbc467ae49cdb6 Mon Sep 17 00:00:00 2001 From: Bruce Griffith Date: Wed, 16 Jul 2014 11:25:21 -0600 Subject: AMD Steppe Eagle: Add 32-bit Fletcher's Checksum computation The AMD Platform Security Processor (PSP) requires a Fletcher's Checksum at the end of the PSP directory. This code implements a Fletcher's Checksum by reading bytes from stdin and writes the bytes back to stdout with a checksum inserted into the byte stream at the appropriate offset. This utility is used on PSP binaries during coreboot build. Include a runtime debug option such that the command: fletcher --print file_with_cksum.bin will print out the computed checksum value for debugging. The compile-time debug option is retained that allows -DDEBUG to be added to the compilation line. This option has the same effect as "--print". Change-Id: I506a479d8204ca4f8267d53aa152ac4b473dbc75 Signed-off-by: Bruce Griffith Reviewed-on: http://review.coreboot.org/6676 Reviewed-by: WANG Siyuan Tested-by: build bot (Jenkins) Reviewed-by: Zheng Bao --- util/fletcher/Makefile | 37 ++++++++++++++ util/fletcher/fletcher.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 util/fletcher/Makefile create mode 100644 util/fletcher/fletcher.c diff --git a/util/fletcher/Makefile b/util/fletcher/Makefile new file mode 100644 index 0000000000..4f3957c632 --- /dev/null +++ b/util/fletcher/Makefile @@ -0,0 +1,37 @@ +#***************************************************************************** +# +# Copyright (c) 2014, Sage Electronic Engineering, LLC +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Advanced Micro Devices, Inc. nor the names of +# its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#***************************************************************************** +HOSTCC ?= gcc + +fletcher_exe : fletcher.c + $(HOSTCC) fletcher.c -o fletcher + +fletcher : fletcher_exe + +clean: + @rm -f fletcher.o fletcher fletcher.exe diff --git a/util/fletcher/fletcher.c b/util/fletcher/fletcher.c new file mode 100644 index 0000000000..3147d50376 --- /dev/null +++ b/util/fletcher/fletcher.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1998-2006 The TCPDUMP project + * 2014 Sage Electronic Engineering, LLC + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code + * distributions retain the above copyright notice and this paragraph + * in its entirety, and (2) distributions including binary code include + * the above copyright notice and this paragraph in its entirety in + * the documentation or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND + * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT + * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * Original code by Hannes Gredler + * Rewritten for Fletcher32 by Bruce Griffith + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_PSP_DIRECTORY_SIZE 512 + +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; + +/* + * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3. + * The checksum field of the passed PDU does not need to be reset to zero. + * + * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of + * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an + * alternative to cyclical redundancy checks because it provides error- + * detection properties similar to cyclical redundancy checks but at the + * cost of a simple summation technique. Its characteristics were first + * published in IEEE Transactions on Communications in January 1982. One + * version has been adopted by ISO for use in the class-4 transport layer + * of the network protocol. + * + * This program expects: + * stdin: The input file to compute a checksum for. The input file + * not be longer than 256 bytes. + * stdout: Copied from the input file with the Fletcher's Checksum + * inserted 8 bytes after the beginning of the file. + * stderr: Used to print out error messages. + */ + +uint32_t fletcher32 (const uint16_t *pptr, int length) +{ + + uint32_t c0; + uint32_t c1; + uint32_t checksum; + int index; + + c0 = 0xFFFF; + c1 = 0xFFFF; + + for (index = 0; index < length; index++) { + /* + * Ignore the contents of the checksum field. + */ + c0 += *(pptr++); + c1 += c0; + if ((index % 360) == 0) { + c0 = (c0 & 0xFFFF) + (c0 >> 16); // Sum0 modulo 65535 + the overflow + c1 = (c1 & 0xFFFF) + (c1 >> 16); // Sum1 modulo 65535 + the overflow + } + + } + + c0 = (c0 & 0xFFFF) + (c0 >> 16); // Sum0 modulo 65535 + the overflow + c1 = (c1 & 0xFFFF) + (c1 >> 16); // Sum1 modulo 65535 + the overflow + checksum = (c1 << 16) | c0; + + return checksum; +} + +int main(int argc, char **argv) +{ + uint32_t checksum = 0xFFFFFFFF; + struct stat filestat = {}; + int retcode = EINVAL; + size_t filesize = 0; + char debugoption[] = "--print"; + + uint16_t buffer[MAX_PSP_DIRECTORY_SIZE / sizeof(uint16_t)]; + + retcode = fstat(fileno(stdin), &filestat); + filesize = filestat.st_size; + if (retcode < 0) { + perror("FLETCHER32"); + return errno; + } else if (!((12 < filesize) && (filesize <= sizeof(buffer)))) { + fprintf(stderr, "FLETCHER32: input file is not valid for this program.\n"); + return EINVAL; + } + retcode = read(fileno(stdin), (void *)buffer, filesize); + if (retcode < 0) { + perror("FLETCHER32"); + return errno; + } + + checksum = fletcher32(&buffer[2], filesize/2 - 2); + *((uint32_t *)& buffer[2]) = checksum; +#ifndef DEBUG + if ((argc == 2) && !strncmp(argv[1], debugoption, sizeof(debugoption+1))) { +#endif + fprintf(stderr, "Fletcher's Checksum: %x\n", checksum); +#ifndef DEBUG + } +#endif + + retcode = write(fileno(stdout), buffer, filesize); + if (retcode < 0) { + perror("FLETCHER32"); + return errno; + } + + return 0; +} -- cgit v1.2.3