Stefan Reinauer has uploaded this change for review. ( https://review.coreboot.org/c/em100/+/37129 )
Change subject: WIP: hook up external config code ......................................................................
WIP: hook up external config code
Need to add datastructure to tar_for_each callback
Change-Id: I581636342448ae75638af84090d58ae41b07fb29 Signed-off-by: Stefan Reinauer stefan.reinauer@coreboot.org --- M Makefile A README.em100pro A TOT-patch.diff A chips.c M em100.c M em100.h M makechips.sh M tar.c 8 files changed, 517 insertions(+), 31 deletions(-)
git pull ssh://review.coreboot.org:29418/em100 refs/changes/29/37129/1
diff --git a/Makefile b/Makefile index 448c798..3b598fe 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@
XZ = xz/xz_crc32.c xz/xz_crc64.c xz/xz_dec_bcj.c xz/xz_dec_lzma2.c xz/xz_dec_stream.c SOURCES = em100.c firmware.c fpga.c hexdump.c sdram.c spi.c system.c trace.c usb.c -SOURCES += curl.c tar.c $(XZ) +SOURCES += curl.c chips.c tar.c $(XZ)
OBJECTS = $(SOURCES:.c=.o)
@@ -66,7 +66,7 @@ printf " CC $@\n" $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
-dep: $(SOURCES) em100pro_chips.h +dep: $(SOURCES) # em100pro_chips.h $(CC) $(CFLAGS) $(INCLUDES) -MM $(SOURCES) > .dependencies
makechips.sh: makedpfw makechips @@ -74,6 +74,8 @@ clean: rm -f em100 makedpfw makechips rm -f $(OBJECTS) # $(SOURCES:.c=.d) + rm -f $(SOURCES:.c=.gcno) $(SOURCES:.c=.gcda) + rm -f makechips.gcno makechips.gcda makedpfw.gcno makedpfw.gcda rm -rf configs firmware rm -f .dependencies
diff --git a/README.em100pro b/README.em100pro new file mode 100644 index 0000000..e054f08 --- /dev/null +++ b/README.em100pro @@ -0,0 +1,9 @@ +Latest software: +https://eip.dediprog.com/ftp/download.php?path=Customer%20Usage/EM100Pro_4.3... +https://eip.dediprog.com/ftp/download.php?path=Customer%20Usage/02270091.zip +https://eip.dediprog.com/ftp/download.php?path=dediprog_evy/00332018.dpfw + +Bugs in the Installer: +all chips: filename=chipname. +configs/MX25L12839F.cfg, chipname=MX25L12839 + diff --git a/TOT-patch.diff b/TOT-patch.diff new file mode 100644 index 0000000..01a00dc --- /dev/null +++ b/TOT-patch.diff @@ -0,0 +1,84 @@ +diff --git a/usb-protocol.md b/usb-protocol.md +index 34aa785..475a2ed 100644 +--- a/usb-protocol.md ++++ b/usb-protocol.md +@@ -234,6 +234,40 @@ has a 1 byte address and is 2 bytes wide (referred to as a0, a1). This includes + some information of the former file protocol-notes.txt. Please help complete this + information. + ++#### 2.6.1. ???? ++ ++FPGA command: ++ ++| Address | R/W | Description | ++|---------|-----|---------------------------| ++| 0x10 | ?/W | ?? | ++ ++Data written on G2 during early initialization, value 00 00. ++ ++ ++#### 2.6.1. ???? ++ ++FPGA command: ++ ++| Address | R/W | Description | ++|---------|-----|---------------------------| ++| 0x28 | R/? | ?? | ++ ++Data read on G2 during early initialization, returned 00 00. ++ ++#### 2.6.1. ???? ++ ++FPGA command: ++ ++| Address | R/W | Description | ++|---------|-----|---------------------------| ++| 0x2a | R/W | ?? | ++ ++Data read on G2 during early initialization, returned 00 02, same value written ++back. Written / Read during chip configuration. ++ ++ ++ + #### 2.6.1. ???? + + FPGA command: +@@ -342,13 +376,36 @@ Device | MCU version | FPGA version | + EM100Pro | 2.27 | 0.091 | + EM100Pro-G2 | 3.3 | 2.014 | + +-#### 2.6.10. CS Pin Selection ++ ++#### 2.6.10. ???? + + FPGA command: + + | Address | R/W | Description | + |---------|-----|---------------------------| +-| 0xE0 | WO | Set default address space | ++| 0x81 | ?/W | ?? | ++ ++Written on G2 during initialization, value 00 ++Written during chip configuration ++ ++ ++#### 2.6.10. ???? ++ ++FPGA command: ++ ++| Address | R/W | Description | ++|---------|-----|---------------------------| ++| 0xc4 | ?/W | ?? | ++ ++Written during chip initialization ++ ++#### 2.6.10. CS Pin Selection ++ ++FPGA command: ++ ++| Address | R/W | Description | ++|---------|-----|-------------------| ++| 0xE0 | WO | CS pin selection | + + | Bit | Description | Initial value | + |-----|------------------------------|---------------| diff --git a/chips.c b/chips.c new file mode 100644 index 0000000..9960ead --- /dev/null +++ b/chips.c @@ -0,0 +1,330 @@ +/* + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdint.h> +#ifdef __APPLE__ +#include <libkern/OSByteOrder.h> +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#include <architecture/byte_order.h> + #if BYTE_ORDER == LITTLE_ENDIAN + #define le32toh(x) (x) + #define le16toh(x) (x) + #define htobe16(x) bswap_16(x) + #else + #define le32toh(x) bswap_32(x) + #define le16toh(x) bswap_16(x) + #define htobe16(x) (x) + #endif +#else +#include <endian.h> +#endif + +#include "em100.h" + +#define DEDIPROG_CFG_PRO_MAX_ENTRIES 212 + +#define DEDIPROG_CFG_PRO_SIZE 176 +#define DEDIPROG_CFG_PRO_SIZE_SFDP 256 +#define DEDIPROG_CFG_PRO_SIZE_SRST 144 + +#define DEDIPROG_CFG_MAGIC 0x67666344 /* 'Dcfg' */ +#define DEDIPROG_SFDP_MAGIC 0x50444653 /* 'SFDP' */ +#define DEDIPROG_SRST_MAGIC 0x54535253 /* 'SRST' */ +#define DEDIPROG_PROT_MAGIC 0x544f5250 /* 'PROT' */ + +#define INIT_SEQUENCE_REIGSTER_OFFSET_0 0x2300 +#define INIT_SEQUENCE_REIGSTER_OFFSET_1 0x1100 + +/* Init sequence and file format: + * + * All v1.1 dediprog configuration files are 176 bytes and all values are + * encoded as little endian format. + + * At offset init_offset the init sequence consists of init entries that are + * sent to endpoint 1. There are 2 sets of entries separated by a 32-bit + * terminator of 0xffffffff. Each entry consists of a value and register offset. + * The first set of entries have a base register address of 0x2300 while the + * the second set of entries have a base register address of 0x1100. Each entry + * is sent to the device as <register> <value>, however the data is sent in + * big endian format. Additionally, each entry is sent as a 16-byte transfer + * with the remaining bytes all 0's. + * + * Configuration files that are >= 436 bytes contain SFDP data, separated by + * the magic value 'SFDP' while those that are 584 bytes contain SRST data + * separated by the magic value 'SRST' and containing 0 or 3 entries followed + * by PROT data in the rest of the buffer. Unfortunately there does not seem + * to be any change in the version fields and these are still reported as 1.1. + */ + + +struct dediprog_cfg_hdr { + uint32_t magic; + uint16_t ver_min; + uint16_t ver_maj; + uint32_t init_offset; + uint32_t chip_size; + uint32_t vendor_name_offset; + uint32_t chip_name_offset; + uint32_t unknown_offset[2]; +} __attribute__((packed)); + +struct dediprog_cfg_pro { + struct dediprog_cfg_hdr hdr; + uint8_t payload[DEDIPROG_CFG_PRO_SIZE-sizeof(struct dediprog_cfg_hdr)]; +} __attribute__((packed)); + + +struct dediprog_cfg_init_entry { + uint16_t value; + uint16_t reg; +} __attribute__((packed)); + +unsigned char cfg_buffer[DEDIPROG_CFG_PRO_SIZE]; + +static int parse_and_output_config(struct dediprog_cfg_pro *cfg, chipdesc *chip) +{ + struct dediprog_cfg_init_entry *entry, *end; + struct dediprog_cfg_hdr *hdr; + const char *vendor, *chip_name; + uint16_t reg_offset; + int entries = 0; + + hdr = &cfg->hdr; + + /* The magic number is actually string, but it can be converted to + * a host ordered 32-bit number. */ + hdr->magic= le32toh(hdr->magic); + + if (hdr->magic != DEDIPROG_CFG_MAGIC) { + fprintf(stderr, "Invalid magic number: 0x%x\n", hdr->magic); + return -1; + } + + /* Convert all header values from little endian to host byte order. */ + hdr->ver_min = le16toh(hdr->ver_min); + hdr->ver_maj = le16toh(hdr->ver_maj); + hdr->init_offset = le32toh(hdr->init_offset); + hdr->chip_size = le32toh(hdr->chip_size); + hdr->vendor_name_offset = le32toh(hdr->vendor_name_offset); + hdr->chip_name_offset = le32toh(hdr->chip_name_offset); + + if (hdr->ver_maj != 1 && hdr->ver_min != 1) { + fprintf(stderr, "Invalid version number: %d.%d\n", hdr->ver_maj, + hdr->ver_min); + return -1; + } + + /* Adjust the offsets to be into the payload of the config file. */ + hdr->init_offset -= sizeof(*hdr); + hdr->vendor_name_offset -= sizeof(*hdr); + hdr->chip_name_offset -= sizeof(*hdr); + + vendor = (void *)&cfg->payload[hdr->vendor_name_offset]; + chip_name = (void *)&cfg->payload[hdr->chip_name_offset]; + + /* Since configs.tar is resident, we don't have to malloc */ + chip->vendor = (const char *)vendor; + chip->name = (const char *)chip_name; + chip->size = hdr->chip_size; + + printf("%s %s (%d kB) */\n", + vendor, chip_name, hdr->chip_size/1024); + + entry = (void *)&cfg->payload[hdr->init_offset]; + end = (void *)&cfg[1]; /* 1 past the last entry */ + + reg_offset = INIT_SEQUENCE_REIGSTER_OFFSET_0; + + for (; entry != end; entry++) { + uint8_t *reg, *value; + + /* Convert from little endian to host format. */ + entry->value = le16toh(entry->value); + entry->reg = le16toh(entry->reg); + + if (entry->value == 0xffff && entry->reg == 0xffff) { + reg_offset = INIT_SEQUENCE_REIGSTER_OFFSET_1; + continue; + } + + entry->reg += reg_offset; + + /* Convert from host to big endian format. */ + entry->value = htobe16(entry->value); + entry->reg = htobe16(entry->reg); + + value = (void *)&entry->value; + reg = (void *)&entry->reg; + + chip->init[entries][0] = reg[0]; + chip->init[entries][1] = reg[1]; + chip->init[entries][2] = value[0]; + chip->init[entries][3] = value[1]; + + printf(" Entry %d\n", entries); + ++entries; + } + + return entries; +} + +static int parse_and_output_sfdp(chipdesc *chip, void **ptr, int *length, int entries) +{ + int i, len = 0; + unsigned char *sfdp_buffer = (unsigned char *)*ptr; + + if (*length < DEDIPROG_CFG_PRO_SIZE_SFDP) { + fprintf(stderr, "Error reading SFDP\n"); + return -1; + } + + chip->init[entries][0] = 0x23; + chip->init[entries][1] = 0xc9; + chip->init[entries][2] = 0x00; + chip->init[entries][3] = 0x01; + + len++; + + for (i = 0; i < DEDIPROG_CFG_PRO_SIZE_SFDP; i+=2) { + chip->init[entries+len][0] = 0x23; + chip->init[entries+len][1] = 0xc1; + chip->init[entries+len][2] = sfdp_buffer[i+1]; + chip->init[entries+len][3] = sfdp_buffer[i]; + len++; + } + + *ptr += DEDIPROG_CFG_PRO_SIZE_SFDP; + *length -= DEDIPROG_CFG_PRO_SIZE_SFDP; + + return len; +} + +static int parse_and_output_srst(chipdesc *chip, void **ptr, int *length, int entries) +{ + int i, len = 0; + uint32_t magic; + unsigned char *srst_buffer = (unsigned char *)*ptr; + + if (*length < DEDIPROG_CFG_PRO_SIZE_SRST) { + fprintf(stderr, "Error reading SRST\n"); + return -1; + } + + /* SRST has 0 or 3 entries before PROT */ + memcpy(&magic, &srst_buffer[0], sizeof(magic)); + + if (magic != DEDIPROG_PROT_MAGIC) { + int j; + + for (j = 0; j < 3; j++) { + chip->init[entries+len][0] = 0x23; + chip->init[entries+len][1] = srst_buffer[j*4+2]; + chip->init[entries+len][2] = srst_buffer[j*4+1]; + chip->init[entries+len][3] = srst_buffer[j*4]; + len++; + } + + /* Start after SFDP data and PROT magic */ + i = 16; + } else { + /* Start after PROT magic */ + i = 4; + } + + chip->init[entries+len][0] = 0x23; + chip->init[entries+len][1] = 0xc4; + chip->init[entries+len][2] = 0x00; + chip->init[entries+len][3] = 0x01; + len++; + + for (; i < DEDIPROG_CFG_PRO_SIZE_SRST; i+=2) { + chip->init[entries+len][0] = 0x23; + chip->init[entries+len][1] = 0xc5; + chip->init[entries+len][2] = srst_buffer[i+1]; + chip->init[entries+len][3] = srst_buffer[i]; + len++; + } + + *ptr += DEDIPROG_CFG_PRO_SIZE_SRST; + *length -= DEDIPROG_CFG_PRO_SIZE_SRST; + + return len; +} + +int parse_dcfg(chipdesc *chip, TFILE *dcfg) +{ + struct dediprog_cfg_pro *cfg; + int init_len = 0; + uint32_t magic; + + void *ptr = (void *)dcfg->address; + int length = dcfg->length; + + if (length < sizeof(cfg_buffer)) { + /* Not a config file */ + return 1; + } + cfg = (struct dediprog_cfg_pro *)ptr; + + init_len = parse_and_output_config(cfg, chip); + if (init_len < 0) { + fprintf(stderr, "Error parsing Dcfg\n"); + } + + ptr += DEDIPROG_CFG_PRO_SIZE; + length -= DEDIPROG_CFG_PRO_SIZE; + + /* Handle any extra data */ + while (length) { + int ret = 0; + + magic = *(uint32_t *)ptr; + ptr+=sizeof(uint32_t); + length-=sizeof(uint32_t); + + switch (magic) { + case DEDIPROG_SFDP_MAGIC: + printf("SFDP\n"); + ret = parse_and_output_sfdp(chip, &ptr, &length, init_len); + break; + case DEDIPROG_SRST_MAGIC: + printf("SRST\n"); + ret = parse_and_output_srst(chip, &ptr, &length, init_len); + break; + default: + fprintf(stderr, "Unknown magic: 0x%08x\n", magic); + break; + } + + if (ret < 0) { + printf("FAILED.\n"); + return 1; + } + init_len += ret; + } + + chip->init_len = init_len; + + return 0; +} diff --git a/em100.c b/em100.c index 868f5b0..9b567c4 100644 --- a/em100.c +++ b/em100.c @@ -29,8 +29,8 @@
#include "em100.h"
-/* SPI flash chips parameters definition */ -#include "em100pro_chips.h" +TFILE *configs; +char *database_version;
volatile int do_exit_flag = 0;
@@ -602,6 +602,14 @@ return 1; }
+ +static void get_chip_type_entry(char *name, TFILE *dcfg, int ok __unused) +{ + chipdesc chip; + parse_dcfg(&chip, &dcfg); + chipdesc chip = +} + /** * Tries to identify the currently emulated SPI flash by looking at * known registers in the FPGA and matches those bits with the @@ -620,7 +628,9 @@ return 1; if (!read_fpga_register(em100, FPGA_REG_DEVID, &devid)) return 1; - +#warning FIXME +#if 0 + tar_for_each(configs, get_chip_type_entry) for (chip = chips; chip->name != NULL; chip++) { uint16_t comp;
@@ -631,7 +641,7 @@
break; } - +#endif if (!chip) return 1;
@@ -680,31 +690,46 @@ return strdup(file); }
+ static chipdesc *setup_chips(const char *desiredchip) { - const chipdesc *chip = chips; - if (desiredchip) { - do { - if (strcasecmp(desiredchip, chip->name) == 0) { - printf("will emulate '%s'\n", chip->name); - break; - } - } while ((++chip)->name); + static chipdesc chip; + configs = tar_load_compressed(get_em100_file("configs.tar.xz")); + if (!configs) { + printf("Can't find chip configs in $EM100_HOME/configs.tar.xz.\n"); + return NULL; + } + + TFILE *version = tar_find(configs,"configs/VERSION"); + if (!version) { + printf("Can't find VERSION of chip configs.\n"); + return NULL; + } + database_version = (char *)version->address; + tar_close(version);
- if (chip->name == NULL) { + if (desiredchip) { + char chipname[256]; + sprintf(chipname, "configs/%s.cfg", desiredchip); + /* TODO: case insensitive search or search for name inside + * config file + */ + TFILE *dcfg = tar_find(configs, chipname); + if (!dcfg) { printf("Supported chips:\n"); - chip = chips; - do { - printf("%s ", chip->name); - } while ((++chip)->name); + // TODO iterate through all chips, print names + tar_ls(configs); printf("\n\nCould not find emulation for '%s'.\n", desiredchip); - return NULL; } - + printf("will emulate '%s'\n", desiredchip); + parse_dcfg(&chip, dcfg); + return &chip; // TODO return chipdesc } - return chip; + // Previously we would just return the first chip if desiredchip was + // not set. TODO figure out the right behavior. + return NULL; }
static const struct option longopts[] = { @@ -863,7 +888,7 @@ }
const chipdesc *chip = setup_chips(desiredchip); - if (!chip) + if (desiredchip && !chip) return 1;
printf("MCU version: %d.%02d\n", em100.mcu >> 8, em100.mcu & 0xff); @@ -892,7 +917,7 @@ printf("Serial number: EM%06d\n", em100.serialno); else printf("Serial number: N.A.\n"); - printf("SPI flash database: %s\n", VERSION); + printf("SPI flash database: %s\n", database_version); get_current_state(&em100); get_current_pin_state(&em100); printf("\n"); diff --git a/em100.h b/em100.h index 1e9addc..1a6fc57 100644 --- a/em100.h +++ b/em100.h @@ -32,6 +32,16 @@ uint8_t hwversion; };
+#define NUM_INIT_ENTRIES 212 +#define BYTES_PER_INIT_ENTRY 4 +typedef struct { + const char *vendor; + const char *name; + unsigned int size; + uint8_t init[NUM_INIT_ENTRIES][BYTES_PER_INIT_ENTRY]; + int init_len; +} chipdesc; + /* Hardware versions */ #define HWVERSION_EM100PRO 4 #define HWVERSION_EM100PRO_G2 6 @@ -173,6 +183,7 @@ } TFILE; TFILE *tar_find(TFILE *tfile, char *name); TFILE *tar_load_compressed(char *filename); +int tar_for_each(TFILE *tfile, void (*run)(char *, TFILE *, int)); int tar_close(TFILE *tfile); int tar_ls(TFILE *tfile); int test_tar(void); @@ -188,4 +199,7 @@ //char *get_em100_home(void); char *get_em100_file(char *name);
+/* Chips */ +int parse_dcfg(chipdesc *chip, TFILE *dcfg); + #endif diff --git a/makechips.sh b/makechips.sh index 61d7357..ec14440 100755 --- a/makechips.sh +++ b/makechips.sh @@ -49,7 +49,7 @@ rm -rf $TEMP exit 1 fi - +VERSION="4.3.04-Beta J" echo " Creating configs..." mkdir -p $WD/configs cp -a $TEMP/Program\ Files/DediProg/EM100/config/EM100Pro/*.cfg $WD/configs diff --git a/tar.c b/tar.c index 70f5b87..249bea9 100644 --- a/tar.c +++ b/tar.c @@ -60,7 +60,7 @@ return chksum; }
-int tar_ls(TFILE *tfile) +int tar_for_each(TFILE *tfile, void (*run)(char *, TFILE *, int)) { size_t i = 0;
@@ -73,7 +73,15 @@ unsigned int size = strtol(f->size, NULL, 8); unsigned int cksum = strtol(f->checksum, NULL, 8); unsigned int ok = (checksum(f) == cksum); - printf("%s %s\n", f->name, ok?"✔":"✘"); + + if (f->type == '0') { + TFILE s; + s.address = tfile->address + i + sizeof(tar_header_t); + s.length = size; + s.alloc = 0; + + (*run)(f->name, &s, ok); + }
if(!ok) break; @@ -83,6 +91,17 @@ return 0; }
+static void tar_ls_entry(char *name, TFILE *file __unused, int ok) +{ + printf("%s %s\n", name, ok?"✔":"✘"); +} + +int tar_ls(TFILE *tfile) +{ + tar_for_each(tfile, tar_ls_entry); + return 0; +} + TFILE *tar_find(TFILE *tfile, char *name) { size_t i = 0; @@ -109,7 +128,7 @@
ret->address = tfile->address + i + sizeof(tar_header_t); ret->length = size; - ret->alloc = 1; + ret->alloc = 0;
return ret; } @@ -261,12 +280,14 @@
int tar_close(TFILE *tfile) { - free(tfile->address); - if (tfile->alloc) - free(tfile); + if (tfile->alloc) { + free(tfile->address); + } + free(tfile); return 0; }
+#if 0 int test_tar(void) { TFILE *firmware; @@ -290,3 +311,4 @@
return 0; } +#endif
Stefan Reinauer has abandoned this change. ( https://review.coreboot.org/c/em100/+/37129 )
Change subject: WIP: hook up external config code ......................................................................
Abandoned
Integrated into I8c360e96ce42fd78141a1564976454711e20f527