summaryrefslogtreecommitdiff
path: root/util/fletcher/fletcher.c
diff options
context:
space:
mode:
authorBruce Griffith <Bruce.Griffith@se-eng.com>2014-07-16 11:25:21 -0600
committerBruce Griffith <Bruce.Griffith@se-eng.com>2014-08-30 00:28:06 +0200
commit3a2310e05c971e3b46e9e91886bbc467ae49cdb6 (patch)
tree26c8d9981dd2bb83f39cd2731ee8c61f9e4c80a0 /util/fletcher/fletcher.c
parent71c0bf6202bee2c17b3e64b377038207f6018dc6 (diff)
downloadcoreboot-3a2310e05c971e3b46e9e91886bbc467ae49cdb6.tar.xz
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.bin >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 <Bruce.Griffith@se-eng.com> Reviewed-on: http://review.coreboot.org/6676 Reviewed-by: WANG Siyuan <wangsiyuanbuaa@gmail.com> Tested-by: build bot (Jenkins) Reviewed-by: Zheng Bao <zheng.bao@amd.com>
Diffstat (limited to 'util/fletcher/fletcher.c')
-rw-r--r--util/fletcher/fletcher.c128
1 files changed, 128 insertions, 0 deletions
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 <hannes@juniper.net>
+ * Rewritten for Fletcher32 by Bruce Griffith <Bruce.Griffith@se-eng.com>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#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;
+}