mail.coreboot.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
List overview
Download
flashrom-gerrit
February 2021
----- 2024 -----
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
flashrom-gerrit@flashrom.org
1 participants
152 discussions
Start a n
N
ew thread
Change in flashrom[master]: tree: Remove forward-declarations for spi masters
by Edward O'Callaghan (Code Review)
17 Feb '21
17 Feb '21
Edward O'Callaghan has submitted this change. (
https://review.coreboot.org/c/flashrom/+/50711
) Change subject: tree: Remove forward-declarations for spi masters ...................................................................... tree: Remove forward-declarations for spi masters Reorder functions to avoid forward-declarations. It looks like for most of the spi masters this has already been done before, I covered remaining small ones in one patch. BUG=b:140394053 TEST=builds Change-Id: I23ff6b79d794876f73b327f18784ca7c04c32c84 Signed-off-by: Anastasia Klimchuk <aklm(a)chromium.org> Reviewed-on:
https://review.coreboot.org/c/flashrom/+/50711
Tested-by: build bot (Jenkins) <no-reply(a)coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec(a)chromium.org> Reviewed-by: Sam McNally <sammc(a)google.com> Reviewed-by: Angel Pons <th3fanbus(a)gmail.com> --- M buspirate_spi.c M ft2232_spi.c M ichspi.c M linux_spi.c M ni845x_spi.c 5 files changed, 436 insertions(+), 466 deletions(-) Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Edward O'Callaghan: Looks good to me, approved Sam McNally: Looks good to me, approved diff --git a/buspirate_spi.c b/buspirate_spi.c index fdfc0e4..eee8daa 100644 --- a/buspirate_spi.c +++ b/buspirate_spi.c @@ -128,11 +128,6 @@ return ret; } -static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr); -static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr); - static struct spi_master spi_master_buspirate = { .features = SPI_MASTER_4BA, .max_data_read = MAX_DATA_UNSPECIFIED, @@ -205,6 +200,99 @@ return ret; } +static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + unsigned int i = 0; + int ret = 0; + + if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16) + return SPI_INVALID_LENGTH; + + /* 3 bytes extra for CS#, len, CS#. */ + if (buspirate_commbuf_grow(writecnt + readcnt + 3)) + return ERROR_OOM; + + /* Assert CS# */ + bp_commbuf[i++] = 0x02; + + bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1); + memcpy(bp_commbuf + i, writearr, writecnt); + i += writecnt; + memset(bp_commbuf + i, 0, readcnt); + + i += readcnt; + /* De-assert CS# */ + bp_commbuf[i++] = 0x03; + + ret = buspirate_sendrecv(bp_commbuf, i, i); + + if (ret) { + msg_perr("Bus Pirate communication error!\n"); + return SPI_GENERIC_ERROR; + } + + if (bp_commbuf[0] != 0x01) { + msg_perr("Protocol error while lowering CS#!\n"); + return SPI_GENERIC_ERROR; + } + + if (bp_commbuf[1] != 0x01) { + msg_perr("Protocol error while reading/writing SPI!\n"); + return SPI_GENERIC_ERROR; + } + + if (bp_commbuf[i - 1] != 0x01) { + msg_perr("Protocol error while raising CS#!\n"); + return SPI_GENERIC_ERROR; + } + + /* Skip CS#, length, writearr. */ + memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt); + + return ret; +} + +static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + int i = 0, ret = 0; + + if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096) + return SPI_INVALID_LENGTH; + + /* 5 bytes extra for command, writelen, readlen. + * 1 byte extra for Ack/Nack. + */ + if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1))) + return ERROR_OOM; + + /* Combined SPI write/read. */ + bp_commbuf[i++] = 0x04; + bp_commbuf[i++] = (writecnt >> 8) & 0xff; + bp_commbuf[i++] = writecnt & 0xff; + bp_commbuf[i++] = (readcnt >> 8) & 0xff; + bp_commbuf[i++] = readcnt & 0xff; + memcpy(bp_commbuf + i, writearr, writecnt); + + ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt); + + if (ret) { + msg_perr("Bus Pirate communication error!\n"); + return SPI_GENERIC_ERROR; + } + + if (bp_commbuf[0] != 0x01) { + msg_perr("Protocol error while sending SPI write/read!\n"); + return SPI_GENERIC_ERROR; + } + + /* Skip Ack. */ + memcpy(readarr, bp_commbuf + 1, readcnt); + + return ret; +} + #define BP_FWVERSION(a,b) ((a) << 8 | (b)) #define BP_HWVERSION(a,b) BP_FWVERSION(a,b) @@ -571,96 +659,3 @@ return 0; } - -static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr) -{ - unsigned int i = 0; - int ret = 0; - - if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16) - return SPI_INVALID_LENGTH; - - /* 3 bytes extra for CS#, len, CS#. */ - if (buspirate_commbuf_grow(writecnt + readcnt + 3)) - return ERROR_OOM; - - /* Assert CS# */ - bp_commbuf[i++] = 0x02; - - bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1); - memcpy(bp_commbuf + i, writearr, writecnt); - i += writecnt; - memset(bp_commbuf + i, 0, readcnt); - - i += readcnt; - /* De-assert CS# */ - bp_commbuf[i++] = 0x03; - - ret = buspirate_sendrecv(bp_commbuf, i, i); - - if (ret) { - msg_perr("Bus Pirate communication error!\n"); - return SPI_GENERIC_ERROR; - } - - if (bp_commbuf[0] != 0x01) { - msg_perr("Protocol error while lowering CS#!\n"); - return SPI_GENERIC_ERROR; - } - - if (bp_commbuf[1] != 0x01) { - msg_perr("Protocol error while reading/writing SPI!\n"); - return SPI_GENERIC_ERROR; - } - - if (bp_commbuf[i - 1] != 0x01) { - msg_perr("Protocol error while raising CS#!\n"); - return SPI_GENERIC_ERROR; - } - - /* Skip CS#, length, writearr. */ - memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt); - - return ret; -} - -static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr) -{ - int i = 0, ret = 0; - - if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096) - return SPI_INVALID_LENGTH; - - /* 5 bytes extra for command, writelen, readlen. - * 1 byte extra for Ack/Nack. - */ - if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1))) - return ERROR_OOM; - - /* Combined SPI write/read. */ - bp_commbuf[i++] = 0x04; - bp_commbuf[i++] = (writecnt >> 8) & 0xff; - bp_commbuf[i++] = writecnt & 0xff; - bp_commbuf[i++] = (readcnt >> 8) & 0xff; - bp_commbuf[i++] = readcnt & 0xff; - memcpy(bp_commbuf + i, writearr, writecnt); - - ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt); - - if (ret) { - msg_perr("Bus Pirate communication error!\n"); - return SPI_GENERIC_ERROR; - } - - if (bp_commbuf[0] != 0x01) { - msg_perr("Protocol error while sending SPI write/read!\n"); - return SPI_GENERIC_ERROR; - } - - /* Skip Ack. */ - memcpy(readarr, bp_commbuf + 1, readcnt); - - return ret; -} diff --git a/ft2232_spi.c b/ft2232_spi.c index 9060973..1fb795b 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -183,10 +183,93 @@ return 0; } +/* Returns 0 upon success, a negative number upon errors. */ static int ft2232_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, - unsigned char *readarr); + unsigned char *readarr) +{ + struct ftdi_context *ftdic = &ftdic_context; + static unsigned char *buf = NULL; + /* failed is special. We use bitwise ops, but it is essentially bool. */ + int i = 0, ret = 0, failed = 0; + size_t bufsize; + static size_t oldbufsize = 0; + + if (writecnt > 65536 || readcnt > 65536) + return SPI_INVALID_LENGTH; + + /* buf is not used for the response from the chip. */ + bufsize = max(writecnt + 9, 260 + 9); + /* Never shrink. realloc() calls are expensive. */ + if (!buf || bufsize > oldbufsize) { + buf = realloc(buf, bufsize); + if (!buf) { + msg_perr("Out of memory!\n"); + /* TODO: What to do with buf? */ + return SPI_GENERIC_ERROR; + } + oldbufsize = bufsize; + } + + /* + * Minimize USB transfers by packing as many commands as possible + * together. If we're not expecting to read, we can assert CS#, write, + * and deassert CS# all in one shot. If reading, we do three separate + * operations. + */ + msg_pspew("Assert CS#\n"); + buf[i++] = SET_BITS_LOW; + buf[i++] = ~ 0x08 & pinlvl; /* assert CS (3rd) bit only */ + buf[i++] = pindir; + + if (writecnt) { + buf[i++] = MPSSE_DO_WRITE | MPSSE_WRITE_NEG; + buf[i++] = (writecnt - 1) & 0xff; + buf[i++] = ((writecnt - 1) >> 8) & 0xff; + memcpy(buf + i, writearr, writecnt); + i += writecnt; + } + + /* + * Optionally terminate this batch of commands with a + * read command, then do the fetch of the results. + */ + if (readcnt) { + buf[i++] = MPSSE_DO_READ; + buf[i++] = (readcnt - 1) & 0xff; + buf[i++] = ((readcnt - 1) >> 8) & 0xff; + ret = send_buf(ftdic, buf, i); + failed = ret; + /* We can't abort here, we still have to deassert CS#. */ + if (ret) + msg_perr("send_buf failed before read: %i\n", ret); + i = 0; + if (ret == 0) { + /* + * FIXME: This is unreliable. There's no guarantee that + * we read the response directly after sending the read + * command. We may be scheduled out etc. + */ + ret = get_buf(ftdic, readarr, readcnt); + failed |= ret; + /* We can't abort here either. */ + if (ret) + msg_perr("get_buf failed: %i\n", ret); + } + } + + msg_pspew("De-assert CS#\n"); + buf[i++] = SET_BITS_LOW; + buf[i++] = pinlvl; + buf[i++] = pindir; + ret = send_buf(ftdic, buf, i); + failed |= ret; + if (ret) + msg_perr("send_buf failed at end: %i\n", ret); + + return failed ? -1 : 0; +} static const struct spi_master spi_master_ft2232 = { .features = SPI_MASTER_4BA, @@ -532,92 +615,4 @@ return ret; } -/* Returns 0 upon success, a negative number upon errors. */ -static int ft2232_spi_send_command(const struct flashctx *flash, - unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, - unsigned char *readarr) -{ - struct ftdi_context *ftdic = &ftdic_context; - static unsigned char *buf = NULL; - /* failed is special. We use bitwise ops, but it is essentially bool. */ - int i = 0, ret = 0, failed = 0; - size_t bufsize; - static size_t oldbufsize = 0; - - if (writecnt > 65536 || readcnt > 65536) - return SPI_INVALID_LENGTH; - - /* buf is not used for the response from the chip. */ - bufsize = max(writecnt + 9, 260 + 9); - /* Never shrink. realloc() calls are expensive. */ - if (!buf || bufsize > oldbufsize) { - buf = realloc(buf, bufsize); - if (!buf) { - msg_perr("Out of memory!\n"); - /* TODO: What to do with buf? */ - return SPI_GENERIC_ERROR; - } - oldbufsize = bufsize; - } - - /* - * Minimize USB transfers by packing as many commands as possible - * together. If we're not expecting to read, we can assert CS#, write, - * and deassert CS# all in one shot. If reading, we do three separate - * operations. - */ - msg_pspew("Assert CS#\n"); - buf[i++] = SET_BITS_LOW; - buf[i++] = ~ 0x08 & pinlvl; /* assert CS (3rd) bit only */ - buf[i++] = pindir; - - if (writecnt) { - buf[i++] = MPSSE_DO_WRITE | MPSSE_WRITE_NEG; - buf[i++] = (writecnt - 1) & 0xff; - buf[i++] = ((writecnt - 1) >> 8) & 0xff; - memcpy(buf + i, writearr, writecnt); - i += writecnt; - } - - /* - * Optionally terminate this batch of commands with a - * read command, then do the fetch of the results. - */ - if (readcnt) { - buf[i++] = MPSSE_DO_READ; - buf[i++] = (readcnt - 1) & 0xff; - buf[i++] = ((readcnt - 1) >> 8) & 0xff; - ret = send_buf(ftdic, buf, i); - failed = ret; - /* We can't abort here, we still have to deassert CS#. */ - if (ret) - msg_perr("send_buf failed before read: %i\n", ret); - i = 0; - if (ret == 0) { - /* - * FIXME: This is unreliable. There's no guarantee that - * we read the response directly after sending the read - * command. We may be scheduled out etc. - */ - ret = get_buf(ftdic, readarr, readcnt); - failed |= ret; - /* We can't abort here either. */ - if (ret) - msg_perr("get_buf failed: %i\n", ret); - } - } - - msg_pspew("De-assert CS#\n"); - buf[i++] = SET_BITS_LOW; - buf[i++] = pinlvl; - buf[i++] = pindir; - ret = send_buf(ftdic, buf, i); - failed |= ret; - if (ret) - msg_perr("send_buf failed at end: %i\n", ret); - - return failed ? -1 : 0; -} - #endif diff --git a/ichspi.c b/ichspi.c index 4209d60..e45b39a 100644 --- a/ichspi.c +++ b/ichspi.c @@ -286,12 +286,40 @@ #define REGWRITE8(off, val) mmio_writeb(val, ich_spibar+(off)) /* Common SPI functions */ -static int find_opcode(OPCODES *op, uint8_t opcode); -static int find_preop(OPCODES *op, uint8_t preop); -static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen); -static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen); -static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset, - uint8_t datalength, uint8_t * data); + +static int find_opcode(OPCODES *op, uint8_t opcode) +{ + int a; + + if (op == NULL) { + msg_perr("\n%s: null OPCODES pointer!\n", __func__); + return -1; + } + + for (a = 0; a < 8; a++) { + if (op->opcode[a].opcode == opcode) + return a; + } + + return -1; +} + +static int find_preop(OPCODES *op, uint8_t preop) +{ + int a; + + if (op == NULL) { + msg_perr("\n%s: null OPCODES pointer!\n", __func__); + return -1; + } + + for (a = 0; a < 2; a++) { + if (op->preop[a] == preop) + return a; + } + + return -1; +} /* for pairing opcodes with their required preop */ struct preop_opcode_pair { @@ -497,131 +525,6 @@ return 0xFF; } -static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt) -{ - uint8_t spi_type; - - spi_type = lookup_spi_type(opcode); - if (spi_type > 3) { - /* Try to guess spi type from read/write sizes. - * The following valid writecnt/readcnt combinations exist: - * writecnt = 4, readcnt >= 0 - * writecnt = 1, readcnt >= 0 - * writecnt >= 4, readcnt = 0 - * writecnt >= 1, readcnt = 0 - * writecnt >= 1 is guaranteed for all commands. - */ - if (readcnt == 0) - /* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS - * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data - * bytes are actual the address, they go to the bus anyhow - */ - spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; - else if (writecnt == 1) // and readcnt is > 0 - spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; - else if (writecnt == 4) // and readcnt is > 0 - spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; - else // we have an invalid case - return SPI_INVALID_LENGTH; - } - int oppos = 2; // use original JEDEC_BE_D8 offset - curopcodes->opcode[oppos].opcode = opcode; - curopcodes->opcode[oppos].spi_type = spi_type; - program_opcodes(curopcodes, 0, ich_generation); - oppos = find_opcode(curopcodes, opcode); - msg_pdbg2("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos); - return oppos; -} - -static int find_opcode(OPCODES *op, uint8_t opcode) -{ - int a; - - if (op == NULL) { - msg_perr("\n%s: null OPCODES pointer!\n", __func__); - return -1; - } - - for (a = 0; a < 8; a++) { - if (op->opcode[a].opcode == opcode) - return a; - } - - return -1; -} - -static int find_preop(OPCODES *op, uint8_t preop) -{ - int a; - - if (op == NULL) { - msg_perr("\n%s: null OPCODES pointer!\n", __func__); - return -1; - } - - for (a = 0; a < 2; a++) { - if (op->preop[a] == preop) - return a; - } - - return -1; -} - -/* Create a struct OPCODES based on what we find in the locked down chipset. */ -static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen) -{ - int a; - uint16_t preop, optype; - uint32_t opmenu[2]; - - if (op == NULL) { - msg_perr("\n%s: null OPCODES pointer!\n", __func__); - return -1; - } - - switch (ich_gen) { - case CHIPSET_ICH7: - case CHIPSET_TUNNEL_CREEK: - case CHIPSET_CENTERTON: - preop = REGREAD16(ICH7_REG_PREOP); - optype = REGREAD16(ICH7_REG_OPTYPE); - opmenu[0] = REGREAD32(ICH7_REG_OPMENU); - opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4); - break; - case CHIPSET_ICH8: - default: /* Future version might behave the same */ - preop = REGREAD16(swseq_data.reg_preop); - optype = REGREAD16(swseq_data.reg_optype); - opmenu[0] = REGREAD32(swseq_data.reg_opmenu); - opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4); - break; - } - - op->preop[0] = (uint8_t) preop; - op->preop[1] = (uint8_t) (preop >> 8); - - for (a = 0; a < 8; a++) { - op->opcode[a].spi_type = (uint8_t) (optype & 0x3); - optype >>= 2; - } - - for (a = 0; a < 4; a++) { - op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff); - opmenu[0] >>= 8; - } - - for (a = 4; a < 8; a++) { - op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff); - opmenu[1] >>= 8; - } - - /* No preopcodes used by default. */ - for (a = 0; a < 8; a++) - op->opcode[a].atomic = 0; - - return 0; -} - static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen) { uint8_t a; @@ -688,6 +591,42 @@ return 0; } +static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt) +{ + uint8_t spi_type; + + spi_type = lookup_spi_type(opcode); + if (spi_type > 3) { + /* Try to guess spi type from read/write sizes. + * The following valid writecnt/readcnt combinations exist: + * writecnt = 4, readcnt >= 0 + * writecnt = 1, readcnt >= 0 + * writecnt >= 4, readcnt = 0 + * writecnt >= 1, readcnt = 0 + * writecnt >= 1 is guaranteed for all commands. + */ + if (readcnt == 0) + /* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS + * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data + * bytes are actual the address, they go to the bus anyhow + */ + spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; + else if (writecnt == 1) // and readcnt is > 0 + spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; + else if (writecnt == 4) // and readcnt is > 0 + spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + else // we have an invalid case + return SPI_INVALID_LENGTH; + } + int oppos = 2; // use original JEDEC_BE_D8 offset + curopcodes->opcode[oppos].opcode = opcode; + curopcodes->opcode[oppos].spi_type = spi_type; + program_opcodes(curopcodes, 0, ich_generation); + oppos = find_opcode(curopcodes, opcode); + msg_pdbg2("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos); + return oppos; +} + /* * Returns -1 if at least one mandatory opcode is inaccessible, 0 otherwise. * FIXME: this should also check for @@ -754,49 +693,59 @@ min_addr, ichspi_bbar); } -/* Read len bytes from the fdata/spid register into the data array. - * - * Note that using len > flash->mst->spi.max_data_read will return garbage or - * may even crash. - */ -static void ich_read_data(uint8_t *data, int len, int reg0_off) +/* Create a struct OPCODES based on what we find in the locked down chipset. */ +static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen) { - int i; - uint32_t temp32 = 0; + int a; + uint16_t preop, optype; + uint32_t opmenu[2]; - for (i = 0; i < len; i++) { - if ((i % 4) == 0) - temp32 = REGREAD32(reg0_off + i); - - data[i] = (temp32 >> ((i % 4) * 8)) & 0xff; + if (op == NULL) { + msg_perr("\n%s: null OPCODES pointer!\n", __func__); + return -1; } -} -/* Fill len bytes from the data array into the fdata/spid registers. - * - * Note that using len > flash->mst->spi.max_data_write will trash the registers - * following the data registers. - */ -static void ich_fill_data(const uint8_t *data, int len, int reg0_off) -{ - uint32_t temp32 = 0; - int i; - - if (len <= 0) - return; - - for (i = 0; i < len; i++) { - if ((i % 4) == 0) - temp32 = 0; - - temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8); - - if ((i % 4) == 3) /* 32 bits are full, write them to regs. */ - REGWRITE32(reg0_off + (i - (i % 4)), temp32); + switch (ich_gen) { + case CHIPSET_ICH7: + case CHIPSET_TUNNEL_CREEK: + case CHIPSET_CENTERTON: + preop = REGREAD16(ICH7_REG_PREOP); + optype = REGREAD16(ICH7_REG_OPTYPE); + opmenu[0] = REGREAD32(ICH7_REG_OPMENU); + opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4); + break; + case CHIPSET_ICH8: + default: /* Future version might behave the same */ + preop = REGREAD16(swseq_data.reg_preop); + optype = REGREAD16(swseq_data.reg_optype); + opmenu[0] = REGREAD32(swseq_data.reg_opmenu); + opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4); + break; } - i--; - if ((i % 4) != 3) /* Write remaining data to regs. */ - REGWRITE32(reg0_off + (i - (i % 4)), temp32); + + op->preop[0] = (uint8_t) preop; + op->preop[1] = (uint8_t) (preop >> 8); + + for (a = 0; a < 8; a++) { + op->opcode[a].spi_type = (uint8_t) (optype & 0x3); + optype >>= 2; + } + + for (a = 0; a < 4; a++) { + op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff); + opmenu[0] >>= 8; + } + + for (a = 4; a < 8; a++) { + op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff); + opmenu[1] >>= 8; + } + + /* No preopcodes used by default. */ + for (a = 0; a < 8; a++) + op->opcode[a].atomic = 0; + + return 0; } /* This function generates OPCODES from or programs OPCODES to ICH according to @@ -834,6 +783,51 @@ } } +/* Fill len bytes from the data array into the fdata/spid registers. + * + * Note that using len > flash->mst->spi.max_data_write will trash the registers + * following the data registers. + */ +static void ich_fill_data(const uint8_t *data, int len, int reg0_off) +{ + uint32_t temp32 = 0; + int i; + + if (len <= 0) + return; + + for (i = 0; i < len; i++) { + if ((i % 4) == 0) + temp32 = 0; + + temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8); + + if ((i % 4) == 3) /* 32 bits are full, write them to regs. */ + REGWRITE32(reg0_off + (i - (i % 4)), temp32); + } + i--; + if ((i % 4) != 3) /* Write remaining data to regs. */ + REGWRITE32(reg0_off + (i - (i % 4)), temp32); +} + +/* Read len bytes from the fdata/spid register into the data array. + * + * Note that using len > flash->mst->spi.max_data_read will return garbage or + * may even crash. + */ +static void ich_read_data(uint8_t *data, int len, int reg0_off) +{ + int i; + uint32_t temp32 = 0; + + for (i = 0; i < len; i++) { + if ((i % 4) == 0) + temp32 = REGREAD32(reg0_off + i); + + data[i] = (temp32 >> ((i % 4) * 8)) & 0xff; + } +} + static int ich7_run_opcode(OPCODE op, uint32_t offset, uint8_t datalength, uint8_t * data, int maxdata) { diff --git a/linux_spi.c b/linux_spi.c index 1ef8f2b..bbd45f3 100644 --- a/linux_spi.c +++ b/linux_spi.c @@ -48,15 +48,65 @@ #define BUF_SIZE_FROM_SYSFS "/sys/module/spidev/parameters/bufsiz" static size_t max_kernel_buf_size; -static int linux_spi_shutdown(void *data); +static int linux_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) +{ + /* Older kernels use a single buffer for combined input and output + data. So account for longest possible command + address, too. */ + return spi_read_chunked(flash, buf, start, len, max_kernel_buf_size - 5); +} + +static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) +{ + /* 5 bytes must be reserved for longest possible command + address. */ + return spi_write_chunked(flash, buf, start, len, max_kernel_buf_size - 5); +} + +static int linux_spi_shutdown(void *data) +{ + if (fd != -1) { + close(fd); + fd = -1; + } + return 0; +} + static int linux_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *txbuf, - unsigned char *rxbuf); -static int linux_spi_read(struct flashctx *flash, uint8_t *buf, - unsigned int start, unsigned int len); -static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, - unsigned int start, unsigned int len); + unsigned char *rxbuf) +{ + int iocontrol_code; + struct spi_ioc_transfer msg[2] = { + { + .tx_buf = (uint64_t)(uintptr_t)txbuf, + .len = writecnt, + }, + { + .rx_buf = (uint64_t)(uintptr_t)rxbuf, + .len = readcnt, + }, + }; + + if (fd == -1) + return -1; + /* The implementation currently does not support requests that + don't start with sending a command. */ + if (writecnt == 0) + return SPI_INVALID_LENGTH; + + /* Just submit the first (write) request in case there is nothing + to read. Otherwise submit both requests. */ + if (readcnt == 0) + iocontrol_code = SPI_IOC_MESSAGE(1); + else + iocontrol_code = SPI_IOC_MESSAGE(2); + + if (ioctl(fd, iocontrol_code, msg) == -1) { + msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno)); + return -1; + } + return 0; +} static const struct spi_master spi_master_linux = { .features = SPI_MASTER_4BA, @@ -174,64 +224,4 @@ return 0; } -static int linux_spi_shutdown(void *data) -{ - if (fd != -1) { - close(fd); - fd = -1; - } - return 0; -} - -static int linux_spi_send_command(const struct flashctx *flash, unsigned int writecnt, - unsigned int readcnt, - const unsigned char *txbuf, - unsigned char *rxbuf) -{ - int iocontrol_code; - struct spi_ioc_transfer msg[2] = { - { - .tx_buf = (uint64_t)(uintptr_t)txbuf, - .len = writecnt, - }, - { - .rx_buf = (uint64_t)(uintptr_t)rxbuf, - .len = readcnt, - }, - }; - - if (fd == -1) - return -1; - /* The implementation currently does not support requests that - don't start with sending a command. */ - if (writecnt == 0) - return SPI_INVALID_LENGTH; - - /* Just submit the first (write) request in case there is nothing - to read. Otherwise submit both requests. */ - if (readcnt == 0) - iocontrol_code = SPI_IOC_MESSAGE(1); - else - iocontrol_code = SPI_IOC_MESSAGE(2); - - if (ioctl(fd, iocontrol_code, msg) == -1) { - msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno)); - return -1; - } - return 0; -} - -static int linux_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) -{ - /* Older kernels use a single buffer for combined input and output - data. So account for longest possible command + address, too. */ - return spi_read_chunked(flash, buf, start, len, max_kernel_buf_size - 5); -} - -static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) -{ - /* 5 bytes must be reserved for longest possible command + address. */ - return spi_write_chunked(flash, buf, start, len, max_kernel_buf_size - 5); -} - #endif // CONFIG_LINUX_SPI == 1 diff --git a/ni845x_spi.c b/ni845x_spi.c index 7b2bea3..153e03e 100644 --- a/ni845x_spi.c +++ b/ni845x_spi.c @@ -50,10 +50,6 @@ static uint16_t io_voltage_in_mV; static bool ignore_io_voltage_limits; -static int ni845x_spi_shutdown(void *data); -static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle); -static void ni845x_spi_print_available_devices(void); - // USB-8452 supported voltages, keep this array in ascending order! static const uint8_t usb8452_io_voltages_in_100mV[5] = { kNi845x12Volts, @@ -129,6 +125,28 @@ } /** + * @brief ni845x_spi_open_resource + * @param resource_handle the resource handle returned by the ni845xFindDevice or ni845xFindDeviceNext + * @param opened_handle the opened handle from the ni845xOpen + * @return the 0 on successful competition, negative error code on failure positive code on warning + */ +static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle) +{ + // NI-845x driver loads the FPGA bitfile at the first time + // which can take couple seconds + if (device_pid == USB8452) + msg_pwarn("Opening NI-8452, this might take a while for the first time\n"); + + int32 tmp = ni845xOpen(resource_handle, opened_handle); + + if (tmp < 0) + ni845x_report_error("ni845xOpen", tmp); + else if (tmp > 0) + ni845x_report_warning("ni845xOpen", tmp); + return tmp; +} + +/** * @param serial a null terminated string containing the serial number of the specific device or NULL * @return the 0 on successful completition, negative error code on failure */ @@ -194,28 +212,6 @@ } /** - * @brief ni845x_spi_open_resource - * @param resource_handle the resource handle returned by the ni845xFindDevice or ni845xFindDeviceNext - * @param opened_handle the opened handle from the ni845xOpen - * @return the 0 on successful competition, negative error code on failure positive code on warning - */ -static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle) -{ - // NI-845x driver loads the FPGA bitfile at the first time - // which can take couple seconds - if (device_pid == USB8452) - msg_pwarn("Opening NI-8452, this might take a while for the first time\n"); - - int32 tmp = ni845xOpen(resource_handle, opened_handle); - - if (tmp < 0) - ni845x_report_error("ni845xOpen", tmp); - else if (tmp > 0) - ni845x_report_warning("ni845xOpen", tmp); - return tmp; -} - -/** * @brief usb8452_spi_set_io_voltage sets the IO voltage for the USB-8452 devices * @param requested_io_voltage_mV the desired IO voltage in mVolts * @param set_io_voltage_mV the IO voltage which was set in mVolts @@ -389,6 +385,24 @@ ni845x_report_error("ni845xCloseFindDeviceHandle", tmp); } +static int ni845x_spi_shutdown(void *data) +{ + int32 ret = 0; + + if (configuration_handle != 0) { + ret = ni845xSpiConfigurationClose(configuration_handle); + if (ret) + ni845x_report_error("ni845xSpiConfigurationClose", ret); + } + + if (device_handle != 0) { + ret = ni845xClose(device_handle); + if (ret) + ni845x_report_error("ni845xClose", ret); + } + return 0; +} + int ni845x_spi_init(void) { char *speed_str = NULL; @@ -486,24 +500,6 @@ return 0; } -static int ni845x_spi_shutdown(void *data) -{ - int32 ret = 0; - - if (configuration_handle != 0) { - ret = ni845xSpiConfigurationClose(configuration_handle); - if (ret) - ni845x_report_error("ni845xSpiConfigurationClose", ret); - } - - if (device_handle != 0) { - ret = ni845xClose(device_handle); - if (ret) - ni845x_report_error("ni845xClose", ret); - } - return 0; -} - static void ni845x_warn_over_max_voltage(const struct flashctx *flash) { if (device_pid == USB8451) { -- To view, visit
https://review.coreboot.org/c/flashrom/+/50711
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I23ff6b79d794876f73b327f18784ca7c04c32c84 Gerrit-Change-Number: 50711 Gerrit-PatchSet: 3 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-MessageType: merged
1
0
0
0
Change in flashrom[master]: serprog.c: Remove forward-declarations
by Edward O'Callaghan (Code Review)
17 Feb '21
17 Feb '21
Edward O'Callaghan has submitted this change. (
https://review.coreboot.org/c/flashrom/+/50713
) Change subject: serprog.c: Remove forward-declarations ...................................................................... serprog.c: Remove forward-declarations Reorder functions to avoid forward-declarations BUG=b:140394053 TEST=builds Change-Id: I6d05b2ad7b1a753aa752b22f9eb60a7b37dff641 Signed-off-by: Anastasia Klimchuk <aklm(a)chromium.org> Reviewed-on:
https://review.coreboot.org/c/flashrom/+/50713
Tested-by: build bot (Jenkins) <no-reply(a)coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec(a)chromium.org> Reviewed-by: Sam McNally <sammc(a)google.com> Reviewed-by: Angel Pons <th3fanbus(a)gmail.com> --- M serprog.c 1 file changed, 222 insertions(+), 239 deletions(-) Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Edward O'Callaghan: Looks good to me, approved Sam McNally: Looks good to me, approved diff --git a/serprog.c b/serprog.c index 1befce1..d583a40 100644 --- a/serprog.c +++ b/serprog.c @@ -42,13 +42,6 @@ #define MSGHEADER "serprog: " -/* - * FIXME: This prototype was added to help reduce diffs for the shutdown - * registration patch, which shifted many lines of code to place - * serprog_shutdown() before serprog_init(). It should be removed soon. - */ -static int serprog_shutdown(void *data); - static uint16_t sp_device_serbuf_size = 16; static uint16_t sp_device_opbuf_size = 300; /* Bitmap of supported commands */ @@ -295,10 +288,112 @@ return 0; } +/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */ +static int sp_pass_writen(void) +{ + unsigned char header[7]; + msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr); + if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) { + if (sp_flush_stream() != 0) { + return 1; + } + } + /* In case it's just a single byte send it as a single write. */ + if (sp_write_n_bytes == 1) { + sp_write_n_bytes = 0; + header[0] = (sp_write_n_addr >> 0) & 0xFF; + header[1] = (sp_write_n_addr >> 8) & 0xFF; + header[2] = (sp_write_n_addr >> 16) & 0xFF; + header[3] = sp_write_n_buf[0]; + if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0) + return 1; + sp_opbuf_usage += 5; + return 0; + } + header[0] = S_CMD_O_WRITEN; + header[1] = (sp_write_n_bytes >> 0) & 0xFF; + header[2] = (sp_write_n_bytes >> 8) & 0xFF; + header[3] = (sp_write_n_bytes >> 16) & 0xFF; + header[4] = (sp_write_n_addr >> 0) & 0xFF; + header[5] = (sp_write_n_addr >> 8) & 0xFF; + header[6] = (sp_write_n_addr >> 16) & 0xFF; + if (serialport_write(header, 7) != 0) { + msg_perr(MSGHEADER "Error: cannot write write-n command\n"); + return 1; + } + if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) { + msg_perr(MSGHEADER "Error: cannot write write-n data"); + return 1; + } + sp_streamed_transmit_bytes += 7 + sp_write_n_bytes; + sp_streamed_transmit_ops += 1; + sp_opbuf_usage += 7 + sp_write_n_bytes; + sp_write_n_bytes = 0; + sp_prev_was_write = 0; + return 0; +} + +static int sp_execute_opbuf_noflush(void) +{ + if ((sp_max_write_n) && (sp_write_n_bytes)) { + if (sp_pass_writen() != 0) { + msg_perr("Error: could not transfer write buffer\n"); + return 1; + } + } + if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) { + msg_perr("Error: could not execute command buffer\n"); + return 1; + } + msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage); + sp_opbuf_usage = 0; + sp_prev_was_write = 0; + return 0; +} + +static int sp_execute_opbuf(void) +{ + if (sp_execute_opbuf_noflush() != 0) + return 1; + if (sp_flush_stream() != 0) + return 1; + + return 0; +} + static int serprog_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, - unsigned char *readarr); + unsigned char *readarr) +{ + unsigned char *parmbuf; + int ret; + msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt); + if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) { + if (sp_execute_opbuf() != 0) { + msg_perr("Error: could not execute command buffer before sending SPI commands.\n"); + return 1; + } + } + + parmbuf = malloc(writecnt + 6); + if (!parmbuf) { + msg_perr("Error: could not allocate SPI send param buffer.\n"); + return 1; + } + parmbuf[0] = (writecnt >> 0) & 0xFF; + parmbuf[1] = (writecnt >> 8) & 0xFF; + parmbuf[2] = (writecnt >> 16) & 0xFF; + parmbuf[3] = (readcnt >> 0) & 0xFF; + parmbuf[4] = (readcnt >> 8) & 0xFF; + parmbuf[5] = (readcnt >> 16) & 0xFF; + memcpy(parmbuf + 6, writearr, writecnt); + ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt, + readarr); + free(parmbuf); + return ret; +} + static struct spi_master spi_master_serprog = { .features = SPI_MASTER_4BA, .max_data_read = MAX_DATA_READ_UNLIMITED, @@ -310,12 +405,108 @@ .write_aai = default_spi_write_aai, }; +static int sp_check_opbuf_usage(int bytes_to_be_added) +{ + if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) { + /* If this happens in the middle of a page load the page load will probably fail. */ + msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n"); + if (sp_execute_opbuf() != 0) + return 1; + } + return 0; +} + static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val, - chipaddr addr); + chipaddr addr) +{ + msg_pspew("%s\n", __func__); + if (sp_max_write_n) { + if ((sp_prev_was_write) + && (addr == (sp_write_n_addr + sp_write_n_bytes))) { + sp_write_n_buf[sp_write_n_bytes++] = val; + } else { + if ((sp_prev_was_write) && (sp_write_n_bytes)) + sp_pass_writen(); + sp_prev_was_write = 1; + sp_write_n_addr = addr; + sp_write_n_bytes = 1; + sp_write_n_buf[0] = val; + } + sp_check_opbuf_usage(7 + sp_write_n_bytes); + if (sp_write_n_bytes >= sp_max_write_n) + sp_pass_writen(); + } else { + /* We will have to do single writeb ops. */ + unsigned char writeb_parm[4]; + sp_check_opbuf_usage(6); + writeb_parm[0] = (addr >> 0) & 0xFF; + writeb_parm[1] = (addr >> 8) & 0xFF; + writeb_parm[2] = (addr >> 16) & 0xFF; + writeb_parm[3] = val; + sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error + sp_opbuf_usage += 5; + } +} + static uint8_t serprog_chip_readb(const struct flashctx *flash, - const chipaddr addr); -static void serprog_chip_readn(const struct flashctx *flash, uint8_t *buf, - const chipaddr addr, size_t len); + const chipaddr addr) +{ + unsigned char c; + unsigned char buf[3]; + /* Will stream the read operation - eg. add it to the stream buffer, * + * then flush the buffer, then read the read answer. */ + if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) + sp_execute_opbuf_noflush(); + buf[0] = ((addr >> 0) & 0xFF); + buf[1] = ((addr >> 8) & 0xFF); + buf[2] = ((addr >> 16) & 0xFF); + sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error + sp_flush_stream(); // FIXME: return error + if (serialport_read(&c, 1) != 0) + msg_perr(MSGHEADER "readb byteread"); // FIXME: return error + msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c); + return c; +} + +/* Local version that really does the job, doesn't care of max_read_n. */ +static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len) +{ + unsigned char sbuf[6]; + msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len); + /* Stream the read-n -- as above. */ + if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) + sp_execute_opbuf_noflush(); + sbuf[0] = ((addr >> 0) & 0xFF); + sbuf[1] = ((addr >> 8) & 0xFF); + sbuf[2] = ((addr >> 16) & 0xFF); + sbuf[3] = ((len >> 0) & 0xFF); + sbuf[4] = ((len >> 8) & 0xFF); + sbuf[5] = ((len >> 16) & 0xFF); + sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf); + if (sp_flush_stream() != 0) + return 1; + if (serialport_read(buf, len) != 0) { + msg_perr(MSGHEADER "Error: cannot read read-n data"); + return 1; + } + return 0; +} + +/* The externally called version that makes sure that max_read_n is obeyed. */ +static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf, + const chipaddr addr, size_t len) +{ + size_t lenm = len; + chipaddr addrm = addr; + while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) { + sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error + addrm += sp_max_read_n; + lenm -= sp_max_read_n; + } + if (lenm) + sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error +} + static const struct par_master par_master_serprog = { .chip_readb = serprog_chip_readb, .chip_readw = fallback_chip_readw, @@ -327,6 +518,25 @@ .chip_writen = fallback_chip_writen, }; +static int serprog_shutdown(void *data) +{ + if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) + if (sp_execute_opbuf() != 0) + msg_pwarn("Could not flush command buffer.\n"); + if (sp_check_commandavail(S_CMD_S_PIN_STATE)) { + uint8_t dis = 0; + if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0) + msg_pdbg(MSGHEADER "Output drivers disabled\n"); + else + msg_pwarn(MSGHEADER "%s: Warning: could not disable output buffers\n", __func__); + } + /* FIXME: fix sockets on windows(?), especially closing */ + serialport_shutdown(&sp_fd); + if (sp_max_write_n) + free(sp_write_n_buf); + return 0; +} + static enum chipbustype serprog_buses_supported = BUS_NONE; int serprog_init(void) @@ -679,200 +889,6 @@ return 0; } -/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */ -static int sp_pass_writen(void) -{ - unsigned char header[7]; - msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr); - if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) { - if (sp_flush_stream() != 0) { - return 1; - } - } - /* In case it's just a single byte send it as a single write. */ - if (sp_write_n_bytes == 1) { - sp_write_n_bytes = 0; - header[0] = (sp_write_n_addr >> 0) & 0xFF; - header[1] = (sp_write_n_addr >> 8) & 0xFF; - header[2] = (sp_write_n_addr >> 16) & 0xFF; - header[3] = sp_write_n_buf[0]; - if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0) - return 1; - sp_opbuf_usage += 5; - return 0; - } - header[0] = S_CMD_O_WRITEN; - header[1] = (sp_write_n_bytes >> 0) & 0xFF; - header[2] = (sp_write_n_bytes >> 8) & 0xFF; - header[3] = (sp_write_n_bytes >> 16) & 0xFF; - header[4] = (sp_write_n_addr >> 0) & 0xFF; - header[5] = (sp_write_n_addr >> 8) & 0xFF; - header[6] = (sp_write_n_addr >> 16) & 0xFF; - if (serialport_write(header, 7) != 0) { - msg_perr(MSGHEADER "Error: cannot write write-n command\n"); - return 1; - } - if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) { - msg_perr(MSGHEADER "Error: cannot write write-n data"); - return 1; - } - sp_streamed_transmit_bytes += 7 + sp_write_n_bytes; - sp_streamed_transmit_ops += 1; - sp_opbuf_usage += 7 + sp_write_n_bytes; - sp_write_n_bytes = 0; - sp_prev_was_write = 0; - return 0; -} - -static int sp_execute_opbuf_noflush(void) -{ - if ((sp_max_write_n) && (sp_write_n_bytes)) { - if (sp_pass_writen() != 0) { - msg_perr("Error: could not transfer write buffer\n"); - return 1; - } - } - if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) { - msg_perr("Error: could not execute command buffer\n"); - return 1; - } - msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage); - sp_opbuf_usage = 0; - sp_prev_was_write = 0; - return 0; -} - -static int sp_execute_opbuf(void) -{ - if (sp_execute_opbuf_noflush() != 0) - return 1; - if (sp_flush_stream() != 0) - return 1; - - return 0; -} - -static int serprog_shutdown(void *data) -{ - if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) - if (sp_execute_opbuf() != 0) - msg_pwarn("Could not flush command buffer.\n"); - if (sp_check_commandavail(S_CMD_S_PIN_STATE)) { - uint8_t dis = 0; - if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0) - msg_pdbg(MSGHEADER "Output drivers disabled\n"); - else - msg_pwarn(MSGHEADER "%s: Warning: could not disable output buffers\n", __func__); - } - /* FIXME: fix sockets on windows(?), especially closing */ - serialport_shutdown(&sp_fd); - if (sp_max_write_n) - free(sp_write_n_buf); - return 0; -} - -static int sp_check_opbuf_usage(int bytes_to_be_added) -{ - if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) { - /* If this happens in the middle of a page load the page load will probably fail. */ - msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n"); - if (sp_execute_opbuf() != 0) - return 1; - } - return 0; -} - -static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val, - chipaddr addr) -{ - msg_pspew("%s\n", __func__); - if (sp_max_write_n) { - if ((sp_prev_was_write) - && (addr == (sp_write_n_addr + sp_write_n_bytes))) { - sp_write_n_buf[sp_write_n_bytes++] = val; - } else { - if ((sp_prev_was_write) && (sp_write_n_bytes)) - sp_pass_writen(); - sp_prev_was_write = 1; - sp_write_n_addr = addr; - sp_write_n_bytes = 1; - sp_write_n_buf[0] = val; - } - sp_check_opbuf_usage(7 + sp_write_n_bytes); - if (sp_write_n_bytes >= sp_max_write_n) - sp_pass_writen(); - } else { - /* We will have to do single writeb ops. */ - unsigned char writeb_parm[4]; - sp_check_opbuf_usage(6); - writeb_parm[0] = (addr >> 0) & 0xFF; - writeb_parm[1] = (addr >> 8) & 0xFF; - writeb_parm[2] = (addr >> 16) & 0xFF; - writeb_parm[3] = val; - sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error - sp_opbuf_usage += 5; - } -} - -static uint8_t serprog_chip_readb(const struct flashctx *flash, - const chipaddr addr) -{ - unsigned char c; - unsigned char buf[3]; - /* Will stream the read operation - eg. add it to the stream buffer, * - * then flush the buffer, then read the read answer. */ - if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) - sp_execute_opbuf_noflush(); - buf[0] = ((addr >> 0) & 0xFF); - buf[1] = ((addr >> 8) & 0xFF); - buf[2] = ((addr >> 16) & 0xFF); - sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error - sp_flush_stream(); // FIXME: return error - if (serialport_read(&c, 1) != 0) - msg_perr(MSGHEADER "readb byteread"); // FIXME: return error - msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c); - return c; -} - -/* Local version that really does the job, doesn't care of max_read_n. */ -static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len) -{ - unsigned char sbuf[6]; - msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len); - /* Stream the read-n -- as above. */ - if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) - sp_execute_opbuf_noflush(); - sbuf[0] = ((addr >> 0) & 0xFF); - sbuf[1] = ((addr >> 8) & 0xFF); - sbuf[2] = ((addr >> 16) & 0xFF); - sbuf[3] = ((len >> 0) & 0xFF); - sbuf[4] = ((len >> 8) & 0xFF); - sbuf[5] = ((len >> 16) & 0xFF); - sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf); - if (sp_flush_stream() != 0) - return 1; - if (serialport_read(buf, len) != 0) { - msg_perr(MSGHEADER "Error: cannot read read-n data"); - return 1; - } - return 0; -} - -/* The externally called version that makes sure that max_read_n is obeyed. */ -static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf, - const chipaddr addr, size_t len) -{ - size_t lenm = len; - chipaddr addrm = addr; - while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) { - sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error - addrm += sp_max_read_n; - lenm -= sp_max_read_n; - } - if (lenm) - sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error -} - void serprog_delay(unsigned int usecs) { unsigned char buf[4]; @@ -894,39 +910,6 @@ sp_prev_was_write = 0; } -static int serprog_spi_send_command(const struct flashctx *flash, - unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, - unsigned char *readarr) -{ - unsigned char *parmbuf; - int ret; - msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt); - if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) { - if (sp_execute_opbuf() != 0) { - msg_perr("Error: could not execute command buffer before sending SPI commands.\n"); - return 1; - } - } - - parmbuf = malloc(writecnt + 6); - if (!parmbuf) { - msg_perr("Error: could not allocate SPI send param buffer.\n"); - return 1; - } - parmbuf[0] = (writecnt >> 0) & 0xFF; - parmbuf[1] = (writecnt >> 8) & 0xFF; - parmbuf[2] = (writecnt >> 16) & 0xFF; - parmbuf[3] = (readcnt >> 0) & 0xFF; - parmbuf[4] = (readcnt >> 8) & 0xFF; - parmbuf[5] = (readcnt >> 16) & 0xFF; - memcpy(parmbuf + 6, writearr, writecnt); - ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt, - readarr); - free(parmbuf); - return ret; -} - void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len) { /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits -- To view, visit
https://review.coreboot.org/c/flashrom/+/50713
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I6d05b2ad7b1a753aa752b22f9eb60a7b37dff641 Gerrit-Change-Number: 50713 Gerrit-PatchSet: 2 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-MessageType: merged
1
0
0
0
Change in flashrom[master]: dummyflasher.c: Remove forward-declarations
by Edward O'Callaghan (Code Review)
17 Feb '21
17 Feb '21
Edward O'Callaghan has submitted this change. (
https://review.coreboot.org/c/flashrom/+/50712
) Change subject: dummyflasher.c: Remove forward-declarations ...................................................................... dummyflasher.c: Remove forward-declarations Reorder functions to avoid forward-declarations BUG=b:140394053 TEST=builds Change-Id: Ibfe9f556316ed509cbec522b4c9cb4c9041e5fdd Signed-off-by: Anastasia Klimchuk <aklm(a)chromium.org> Reviewed-on:
https://review.coreboot.org/c/flashrom/+/50712
Tested-by: build bot (Jenkins) <no-reply(a)coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec(a)chromium.org> Reviewed-by: Sam McNally <sammc(a)google.com> Reviewed-by: Angel Pons <th3fanbus(a)gmail.com> --- M dummyflasher.c 1 file changed, 507 insertions(+), 519 deletions(-) Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Edward O'Callaghan: Looks good to me, approved Sam McNally: Looks good to me, approved diff --git a/dummyflasher.c b/dummyflasher.c index 92c30ee..5190282 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -102,19 +102,514 @@ #endif static unsigned int spi_write_256_chunksize = 256; +static enum chipbustype dummy_buses_supported = BUS_NONE; -static int dummy_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr); -static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, - unsigned int start, unsigned int len); -static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); -static void dummy_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr); -static void dummy_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr); -static void dummy_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len); -static uint8_t dummy_chip_readb(const struct flashctx *flash, const chipaddr addr); -static uint16_t dummy_chip_readw(const struct flashctx *flash, const chipaddr addr); -static uint32_t dummy_chip_readl(const struct flashctx *flash, const chipaddr addr); -static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len); +void *dummy_map(const char *descr, uintptr_t phys_addr, size_t len) +{ + msg_pspew("%s: Mapping %s, 0x%zx bytes at 0x%0*" PRIxPTR "\n", + __func__, descr, len, PRIxPTR_WIDTH, phys_addr); + return (void *)phys_addr; +} + +void dummy_unmap(void *virt_addr, size_t len) +{ + msg_pspew("%s: Unmapping 0x%zx bytes at %p\n", __func__, len, virt_addr); +} + +static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) +{ + return spi_write_chunked(flash, buf, start, len, + spi_write_256_chunksize); +} + +static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%02x\n", __func__, addr, val); +} + +static void dummy_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%04x\n", __func__, addr, val); +} + +static void dummy_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%08x\n", __func__, addr, val); +} + +static void dummy_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) +{ + size_t i; + msg_pspew("%s: addr=0x%" PRIxPTR ", len=0x%zx, writing data (hex):", __func__, addr, len); + for (i = 0; i < len; i++) { + if ((i % 16) == 0) + msg_pspew("\n"); + msg_pspew("%02x ", buf[i]); + } +} + +static uint8_t dummy_chip_readb(const struct flashctx *flash, const chipaddr addr) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xff\n", __func__, addr); + return 0xff; +} + +static uint16_t dummy_chip_readw(const struct flashctx *flash, const chipaddr addr) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xffff\n", __func__, addr); + return 0xffff; +} + +static uint32_t dummy_chip_readl(const struct flashctx *flash, const chipaddr addr) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xffffffff\n", __func__, addr); + return 0xffffffff; +} + +static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len) +{ + msg_pspew("%s: addr=0x%" PRIxPTR ", len=0x%zx, returning array of 0xff\n", __func__, addr, len); + memset(buf, 0xff, len); + return; +} + +static struct emu_data* get_data_from_context(const struct flashctx *flash) +{ + if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH)) + return (struct emu_data *)flash->mst->par.data; + else if (dummy_buses_supported & BUS_SPI) + return (struct emu_data *)flash->mst->spi.data; + + return NULL; /* buses was set to BUS_NONE. */ +} + +#if EMULATE_SPI_CHIP +static int emulate_spi_chip_response(unsigned int writecnt, + unsigned int readcnt, + const unsigned char *writearr, + unsigned char *readarr, + struct emu_data *data) +{ + unsigned int offs, i, toread; + static int unsigned aai_offs; + const unsigned char sst25vf040_rems_response[2] = {0xbf, 0x44}; + const unsigned char sst25vf032b_rems_response[2] = {0xbf, 0x4a}; + const unsigned char mx25l6436_rems_response[2] = {0xc2, 0x16}; + const unsigned char w25q128fv_rems_response[2] = {0xef, 0x17}; + + if (writecnt == 0) { + msg_perr("No command sent to the chip!\n"); + return 1; + } + /* spi_blacklist has precedence over spi_ignorelist. */ + for (i = 0; i < data->spi_blacklist_size; i++) { + if (writearr[0] == data->spi_blacklist[i]) { + msg_pdbg("Refusing blacklisted SPI command 0x%02x\n", + data->spi_blacklist[i]); + return SPI_INVALID_OPCODE; + } + } + for (i = 0; i < data->spi_ignorelist_size; i++) { + if (writearr[0] == data->spi_ignorelist[i]) { + msg_cdbg("Ignoring ignorelisted SPI command 0x%02x\n", + data->spi_ignorelist[i]); + /* Return success because the command does not fail, + * it is simply ignored. + */ + return 0; + } + } + + if (data->emu_max_aai_size && (data->emu_status & SPI_SR_AAI)) { + if (writearr[0] != JEDEC_AAI_WORD_PROGRAM && + writearr[0] != JEDEC_WRDI && + writearr[0] != JEDEC_RDSR) { + msg_perr("Forbidden opcode (0x%02x) attempted during " + "AAI sequence!\n", writearr[0]); + return 0; + } + } + + switch (writearr[0]) { + case JEDEC_RES: + if (writecnt < JEDEC_RES_OUTSIZE) + break; + /* offs calculation is only needed for SST chips which treat RES like REMS. */ + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + offs += writecnt - JEDEC_REMS_OUTSIZE; + switch (data->emu_chip) { + case EMULATE_ST_M25P10_RES: + if (readcnt > 0) + memset(readarr, 0x10, readcnt); + break; + case EMULATE_SST_SST25VF040_REMS: + for (i = 0; i < readcnt; i++) + readarr[i] = sst25vf040_rems_response[(offs + i) % 2]; + break; + case EMULATE_SST_SST25VF032B: + for (i = 0; i < readcnt; i++) + readarr[i] = sst25vf032b_rems_response[(offs + i) % 2]; + break; + case EMULATE_MACRONIX_MX25L6436: + if (readcnt > 0) + memset(readarr, 0x16, readcnt); + break; + case EMULATE_WINBOND_W25Q128FV: + if (readcnt > 0) + memset(readarr, 0x17, readcnt); + break; + default: /* ignore */ + break; + } + break; + case JEDEC_REMS: + /* REMS response has wraparound and uses an address parameter. */ + if (writecnt < JEDEC_REMS_OUTSIZE) + break; + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + offs += writecnt - JEDEC_REMS_OUTSIZE; + switch (data->emu_chip) { + case EMULATE_SST_SST25VF040_REMS: + for (i = 0; i < readcnt; i++) + readarr[i] = sst25vf040_rems_response[(offs + i) % 2]; + break; + case EMULATE_SST_SST25VF032B: + for (i = 0; i < readcnt; i++) + readarr[i] = sst25vf032b_rems_response[(offs + i) % 2]; + break; + case EMULATE_MACRONIX_MX25L6436: + for (i = 0; i < readcnt; i++) + readarr[i] = mx25l6436_rems_response[(offs + i) % 2]; + break; + case EMULATE_WINBOND_W25Q128FV: + for (i = 0; i < readcnt; i++) + readarr[i] = w25q128fv_rems_response[(offs + i) % 2]; + break; + default: /* ignore */ + break; + } + break; + case JEDEC_RDID: + switch (data->emu_chip) { + case EMULATE_SST_SST25VF032B: + if (readcnt > 0) + readarr[0] = 0xbf; + if (readcnt > 1) + readarr[1] = 0x25; + if (readcnt > 2) + readarr[2] = 0x4a; + break; + case EMULATE_MACRONIX_MX25L6436: + if (readcnt > 0) + readarr[0] = 0xc2; + if (readcnt > 1) + readarr[1] = 0x20; + if (readcnt > 2) + readarr[2] = 0x17; + break; + case EMULATE_WINBOND_W25Q128FV: + if (readcnt > 0) + readarr[0] = 0xef; + if (readcnt > 1) + readarr[1] = 0x40; + if (readcnt > 2) + readarr[2] = 0x18; + break; + case EMULATE_VARIABLE_SIZE: + if (readcnt > 0) + readarr[0] = (PROGMANUF_ID >> 8) & 0xff; + if (readcnt > 1) + readarr[1] = PROGMANUF_ID & 0xff; + if (readcnt > 2) + readarr[2] = (PROGDEV_ID >> 8) & 0xff; + if (readcnt > 3) + readarr[3] = PROGDEV_ID & 0xff; + break; + default: /* ignore */ + break; + } + break; + case JEDEC_RDSR: + memset(readarr, data->emu_status, readcnt); + break; + /* FIXME: this should be chip-specific. */ + case JEDEC_EWSR: + case JEDEC_WREN: + data->emu_status |= SPI_SR_WEL; + break; + case JEDEC_WRSR: + if (!(data->emu_status & SPI_SR_WEL)) { + msg_perr("WRSR attempted, but WEL is 0!\n"); + break; + } + /* FIXME: add some reasonable simulation of the busy flag */ + data->emu_status = writearr[1] & ~SPI_SR_WIP; + msg_pdbg2("WRSR wrote 0x%02x.\n", data->emu_status); + break; + case JEDEC_READ: + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + /* Truncate to emu_chip_size. */ + offs %= data->emu_chip_size; + if (readcnt > 0) + memcpy(readarr, flashchip_contents + offs, readcnt); + break; + case JEDEC_READ_4BA: + offs = writearr[1] << 24 | writearr[2] << 16 | writearr[3] << 8 | writearr[4]; + /* Truncate to emu_chip_size. */ + offs %= data->emu_chip_size; + if (readcnt > 0) + memcpy(readarr, flashchip_contents + offs, readcnt); + break; + case JEDEC_BYTE_PROGRAM: + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + /* Truncate to emu_chip_size. */ + offs %= data->emu_chip_size; + if (writecnt < 5) { + msg_perr("BYTE PROGRAM size too short!\n"); + return 1; + } + if (writecnt - 4 > data->emu_max_byteprogram_size) { + msg_perr("Max BYTE PROGRAM size exceeded!\n"); + return 1; + } + memcpy(flashchip_contents + offs, writearr + 4, writecnt - 4); + data->emu_modified = 1; + break; + case JEDEC_BYTE_PROGRAM_4BA: + offs = writearr[1] << 24 | writearr[2] << 16 | writearr[3] << 8 | writearr[4]; + /* Truncate to emu_chip_size. */ + offs %= data->emu_chip_size; + if (writecnt < 6) { + msg_perr("BYTE PROGRAM size too short!\n"); + return 1; + } + if (writecnt - 5 > data->emu_max_byteprogram_size) { + msg_perr("Max BYTE PROGRAM size exceeded!\n"); + return 1; + } + memcpy(flashchip_contents + offs, writearr + 5, writecnt - 5); + data->emu_modified = 1; + break; + case JEDEC_AAI_WORD_PROGRAM: + if (!data->emu_max_aai_size) + break; + if (!(data->emu_status & SPI_SR_AAI)) { + if (writecnt < JEDEC_AAI_WORD_PROGRAM_OUTSIZE) { + msg_perr("Initial AAI WORD PROGRAM size too " + "short!\n"); + return 1; + } + if (writecnt > JEDEC_AAI_WORD_PROGRAM_OUTSIZE) { + msg_perr("Initial AAI WORD PROGRAM size too " + "long!\n"); + return 1; + } + data->emu_status |= SPI_SR_AAI; + aai_offs = writearr[1] << 16 | writearr[2] << 8 | + writearr[3]; + /* Truncate to emu_chip_size. */ + aai_offs %= data->emu_chip_size; + memcpy(flashchip_contents + aai_offs, writearr + 4, 2); + aai_offs += 2; + } else { + if (writecnt < JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) { + msg_perr("Continuation AAI WORD PROGRAM size " + "too short!\n"); + return 1; + } + if (writecnt > JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) { + msg_perr("Continuation AAI WORD PROGRAM size " + "too long!\n"); + return 1; + } + memcpy(flashchip_contents + aai_offs, writearr + 1, 2); + aai_offs += 2; + } + data->emu_modified = 1; + break; + case JEDEC_WRDI: + if (data->emu_max_aai_size) + data->emu_status &= ~SPI_SR_AAI; + break; + case JEDEC_SE: + if (!data->emu_jedec_se_size) + break; + if (writecnt != JEDEC_SE_OUTSIZE) { + msg_perr("SECTOR ERASE 0x20 outsize invalid!\n"); + return 1; + } + if (readcnt != JEDEC_SE_INSIZE) { + msg_perr("SECTOR ERASE 0x20 insize invalid!\n"); + return 1; + } + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + if (offs & (data->emu_jedec_se_size - 1)) + msg_pdbg("Unaligned SECTOR ERASE 0x20: 0x%x\n", offs); + offs &= ~(data->emu_jedec_se_size - 1); + memset(flashchip_contents + offs, 0xff, data->emu_jedec_se_size); + data->emu_modified = 1; + break; + case JEDEC_BE_52: + if (!data->emu_jedec_be_52_size) + break; + if (writecnt != JEDEC_BE_52_OUTSIZE) { + msg_perr("BLOCK ERASE 0x52 outsize invalid!\n"); + return 1; + } + if (readcnt != JEDEC_BE_52_INSIZE) { + msg_perr("BLOCK ERASE 0x52 insize invalid!\n"); + return 1; + } + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + if (offs & (data->emu_jedec_be_52_size - 1)) + msg_pdbg("Unaligned BLOCK ERASE 0x52: 0x%x\n", offs); + offs &= ~(data->emu_jedec_be_52_size - 1); + memset(flashchip_contents + offs, 0xff, data->emu_jedec_be_52_size); + data->emu_modified = 1; + break; + case JEDEC_BE_D8: + if (!data->emu_jedec_be_d8_size) + break; + if (writecnt != JEDEC_BE_D8_OUTSIZE) { + msg_perr("BLOCK ERASE 0xd8 outsize invalid!\n"); + return 1; + } + if (readcnt != JEDEC_BE_D8_INSIZE) { + msg_perr("BLOCK ERASE 0xd8 insize invalid!\n"); + return 1; + } + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + if (offs & (data->emu_jedec_be_d8_size - 1)) + msg_pdbg("Unaligned BLOCK ERASE 0xd8: 0x%x\n", offs); + offs &= ~(data->emu_jedec_be_d8_size - 1); + memset(flashchip_contents + offs, 0xff, data->emu_jedec_be_d8_size); + data->emu_modified = 1; + break; + case JEDEC_CE_60: + if (!data->emu_jedec_ce_60_size) + break; + if (writecnt != JEDEC_CE_60_OUTSIZE) { + msg_perr("CHIP ERASE 0x60 outsize invalid!\n"); + return 1; + } + if (readcnt != JEDEC_CE_60_INSIZE) { + msg_perr("CHIP ERASE 0x60 insize invalid!\n"); + return 1; + } + /* JEDEC_CE_60_OUTSIZE is 1 (no address) -> no offset. */ + /* emu_jedec_ce_60_size is emu_chip_size. */ + memset(flashchip_contents, 0xff, data->emu_jedec_ce_60_size); + data->emu_modified = 1; + break; + case JEDEC_CE_C7: + if (!data->emu_jedec_ce_c7_size) + break; + if (writecnt != JEDEC_CE_C7_OUTSIZE) { + msg_perr("CHIP ERASE 0xc7 outsize invalid!\n"); + return 1; + } + if (readcnt != JEDEC_CE_C7_INSIZE) { + msg_perr("CHIP ERASE 0xc7 insize invalid!\n"); + return 1; + } + /* JEDEC_CE_C7_OUTSIZE is 1 (no address) -> no offset. */ + /* emu_jedec_ce_c7_size is emu_chip_size. */ + memset(flashchip_contents, 0xff, data->emu_jedec_ce_c7_size); + data->emu_modified = 1; + break; + case JEDEC_SFDP: + if (data->emu_chip != EMULATE_MACRONIX_MX25L6436) + break; + if (writecnt < 4) + break; + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + + /* SFDP expects one dummy byte after the address. */ + if (writecnt == 4) { + /* The dummy byte was not written, make sure it is read instead. + * Shifting and shortening the read array does achieve this goal. + */ + readarr++; + readcnt--; + } else { + /* The response is shifted if more than 5 bytes are written, because SFDP data is + * already shifted out by the chip while those superfluous bytes are written. */ + offs += writecnt - 5; + } + + /* The SFDP spec implies that the start address of an SFDP read may be truncated to fit in the + * SFDP table address space, i.e. the start address may be wrapped around at SFDP table size. + * This is a reasonable implementation choice in hardware because it saves a few gates. */ + if (offs >= sizeof(sfdp_table)) { + msg_pdbg("Wrapping the start address around the SFDP table boundary (using 0x%x " + "instead of 0x%x).\n", (unsigned int)(offs % sizeof(sfdp_table)), offs); + offs %= sizeof(sfdp_table); + } + toread = min(sizeof(sfdp_table) - offs, readcnt); + memcpy(readarr, sfdp_table + offs, toread); + if (toread < readcnt) + msg_pdbg("Crossing the SFDP table boundary in a single " + "continuous chunk produces undefined results " + "after that point.\n"); + break; + default: + /* No special response. */ + break; + } + if (writearr[0] != JEDEC_WREN && writearr[0] != JEDEC_EWSR) + data->emu_status &= ~SPI_SR_WEL; + return 0; +} +#endif + +static int dummy_spi_send_command(const struct flashctx *flash, unsigned int writecnt, + unsigned int readcnt, + const unsigned char *writearr, + unsigned char *readarr) +{ + unsigned int i; + struct emu_data *emu_data = get_data_from_context(flash); + if (!emu_data) { + msg_perr("No data in flash context!\n"); + return 1; + } + + msg_pspew("%s:", __func__); + + msg_pspew(" writing %u bytes:", writecnt); + for (i = 0; i < writecnt; i++) + msg_pspew(" 0x%02x", writearr[i]); + + /* Response for unknown commands and missing chip is 0xff. */ + memset(readarr, 0xff, readcnt); +#if EMULATE_SPI_CHIP + switch (emu_data->emu_chip) { + case EMULATE_ST_M25P10_RES: + case EMULATE_SST_SST25VF040_REMS: + case EMULATE_SST_SST25VF032B: + case EMULATE_MACRONIX_MX25L6436: + case EMULATE_WINBOND_W25Q128FV: + case EMULATE_VARIABLE_SIZE: + if (emulate_spi_chip_response(writecnt, readcnt, writearr, + readarr, emu_data)) { + msg_pdbg("Invalid command sent to flash chip!\n"); + return 1; + } + break; + default: + break; + } +#endif + msg_pspew(" reading %u bytes:", readcnt); + for (i = 0; i < readcnt; i++) + msg_pspew(" 0x%02x", readarr[i]); + msg_pspew("\n"); + + programmer_delay((writecnt + readcnt) * emu_data->delay_us); + return 0; +} + + static struct spi_master spi_master_dummyflasher = { .features = SPI_MASTER_4BA, @@ -138,8 +633,6 @@ .chip_writen = dummy_chip_writen, }; -static enum chipbustype dummy_buses_supported = BUS_NONE; - static int dummy_shutdown(void *data) { msg_pspew("%s\n", __func__); @@ -541,511 +1034,6 @@ return 0; } -void *dummy_map(const char *descr, uintptr_t phys_addr, size_t len) -{ - msg_pspew("%s: Mapping %s, 0x%zx bytes at 0x%0*" PRIxPTR "\n", - __func__, descr, len, PRIxPTR_WIDTH, phys_addr); - return (void *)phys_addr; -} - -void dummy_unmap(void *virt_addr, size_t len) -{ - msg_pspew("%s: Unmapping 0x%zx bytes at %p\n", __func__, len, virt_addr); -} - -static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%02x\n", __func__, addr, val); -} - -static void dummy_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%04x\n", __func__, addr, val); -} - -static void dummy_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%08x\n", __func__, addr, val); -} - -static void dummy_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) -{ - size_t i; - msg_pspew("%s: addr=0x%" PRIxPTR ", len=0x%zx, writing data (hex):", __func__, addr, len); - for (i = 0; i < len; i++) { - if ((i % 16) == 0) - msg_pspew("\n"); - msg_pspew("%02x ", buf[i]); - } -} - -static uint8_t dummy_chip_readb(const struct flashctx *flash, const chipaddr addr) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xff\n", __func__, addr); - return 0xff; -} - -static uint16_t dummy_chip_readw(const struct flashctx *flash, const chipaddr addr) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xffff\n", __func__, addr); - return 0xffff; -} - -static uint32_t dummy_chip_readl(const struct flashctx *flash, const chipaddr addr) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xffffffff\n", __func__, addr); - return 0xffffffff; -} - -static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len) -{ - msg_pspew("%s: addr=0x%" PRIxPTR ", len=0x%zx, returning array of 0xff\n", __func__, addr, len); - memset(buf, 0xff, len); - return; -} - -#if EMULATE_SPI_CHIP -static int emulate_spi_chip_response(unsigned int writecnt, - unsigned int readcnt, - const unsigned char *writearr, - unsigned char *readarr, - struct emu_data *data) -{ - unsigned int offs, i, toread; - static int unsigned aai_offs; - const unsigned char sst25vf040_rems_response[2] = {0xbf, 0x44}; - const unsigned char sst25vf032b_rems_response[2] = {0xbf, 0x4a}; - const unsigned char mx25l6436_rems_response[2] = {0xc2, 0x16}; - const unsigned char w25q128fv_rems_response[2] = {0xef, 0x17}; - - if (writecnt == 0) { - msg_perr("No command sent to the chip!\n"); - return 1; - } - /* spi_blacklist has precedence over spi_ignorelist. */ - for (i = 0; i < data->spi_blacklist_size; i++) { - if (writearr[0] == data->spi_blacklist[i]) { - msg_pdbg("Refusing blacklisted SPI command 0x%02x\n", - data->spi_blacklist[i]); - return SPI_INVALID_OPCODE; - } - } - for (i = 0; i < data->spi_ignorelist_size; i++) { - if (writearr[0] == data->spi_ignorelist[i]) { - msg_cdbg("Ignoring ignorelisted SPI command 0x%02x\n", - data->spi_ignorelist[i]); - /* Return success because the command does not fail, - * it is simply ignored. - */ - return 0; - } - } - - if (data->emu_max_aai_size && (data->emu_status & SPI_SR_AAI)) { - if (writearr[0] != JEDEC_AAI_WORD_PROGRAM && - writearr[0] != JEDEC_WRDI && - writearr[0] != JEDEC_RDSR) { - msg_perr("Forbidden opcode (0x%02x) attempted during " - "AAI sequence!\n", writearr[0]); - return 0; - } - } - - switch (writearr[0]) { - case JEDEC_RES: - if (writecnt < JEDEC_RES_OUTSIZE) - break; - /* offs calculation is only needed for SST chips which treat RES like REMS. */ - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - offs += writecnt - JEDEC_REMS_OUTSIZE; - switch (data->emu_chip) { - case EMULATE_ST_M25P10_RES: - if (readcnt > 0) - memset(readarr, 0x10, readcnt); - break; - case EMULATE_SST_SST25VF040_REMS: - for (i = 0; i < readcnt; i++) - readarr[i] = sst25vf040_rems_response[(offs + i) % 2]; - break; - case EMULATE_SST_SST25VF032B: - for (i = 0; i < readcnt; i++) - readarr[i] = sst25vf032b_rems_response[(offs + i) % 2]; - break; - case EMULATE_MACRONIX_MX25L6436: - if (readcnt > 0) - memset(readarr, 0x16, readcnt); - break; - case EMULATE_WINBOND_W25Q128FV: - if (readcnt > 0) - memset(readarr, 0x17, readcnt); - break; - default: /* ignore */ - break; - } - break; - case JEDEC_REMS: - /* REMS response has wraparound and uses an address parameter. */ - if (writecnt < JEDEC_REMS_OUTSIZE) - break; - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - offs += writecnt - JEDEC_REMS_OUTSIZE; - switch (data->emu_chip) { - case EMULATE_SST_SST25VF040_REMS: - for (i = 0; i < readcnt; i++) - readarr[i] = sst25vf040_rems_response[(offs + i) % 2]; - break; - case EMULATE_SST_SST25VF032B: - for (i = 0; i < readcnt; i++) - readarr[i] = sst25vf032b_rems_response[(offs + i) % 2]; - break; - case EMULATE_MACRONIX_MX25L6436: - for (i = 0; i < readcnt; i++) - readarr[i] = mx25l6436_rems_response[(offs + i) % 2]; - break; - case EMULATE_WINBOND_W25Q128FV: - for (i = 0; i < readcnt; i++) - readarr[i] = w25q128fv_rems_response[(offs + i) % 2]; - break; - default: /* ignore */ - break; - } - break; - case JEDEC_RDID: - switch (data->emu_chip) { - case EMULATE_SST_SST25VF032B: - if (readcnt > 0) - readarr[0] = 0xbf; - if (readcnt > 1) - readarr[1] = 0x25; - if (readcnt > 2) - readarr[2] = 0x4a; - break; - case EMULATE_MACRONIX_MX25L6436: - if (readcnt > 0) - readarr[0] = 0xc2; - if (readcnt > 1) - readarr[1] = 0x20; - if (readcnt > 2) - readarr[2] = 0x17; - break; - case EMULATE_WINBOND_W25Q128FV: - if (readcnt > 0) - readarr[0] = 0xef; - if (readcnt > 1) - readarr[1] = 0x40; - if (readcnt > 2) - readarr[2] = 0x18; - break; - case EMULATE_VARIABLE_SIZE: - if (readcnt > 0) - readarr[0] = (PROGMANUF_ID >> 8) & 0xff; - if (readcnt > 1) - readarr[1] = PROGMANUF_ID & 0xff; - if (readcnt > 2) - readarr[2] = (PROGDEV_ID >> 8) & 0xff; - if (readcnt > 3) - readarr[3] = PROGDEV_ID & 0xff; - break; - default: /* ignore */ - break; - } - break; - case JEDEC_RDSR: - memset(readarr, data->emu_status, readcnt); - break; - /* FIXME: this should be chip-specific. */ - case JEDEC_EWSR: - case JEDEC_WREN: - data->emu_status |= SPI_SR_WEL; - break; - case JEDEC_WRSR: - if (!(data->emu_status & SPI_SR_WEL)) { - msg_perr("WRSR attempted, but WEL is 0!\n"); - break; - } - /* FIXME: add some reasonable simulation of the busy flag */ - data->emu_status = writearr[1] & ~SPI_SR_WIP; - msg_pdbg2("WRSR wrote 0x%02x.\n", data->emu_status); - break; - case JEDEC_READ: - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - /* Truncate to emu_chip_size. */ - offs %= data->emu_chip_size; - if (readcnt > 0) - memcpy(readarr, flashchip_contents + offs, readcnt); - break; - case JEDEC_READ_4BA: - offs = writearr[1] << 24 | writearr[2] << 16 | writearr[3] << 8 | writearr[4]; - /* Truncate to emu_chip_size. */ - offs %= data->emu_chip_size; - if (readcnt > 0) - memcpy(readarr, flashchip_contents + offs, readcnt); - break; - case JEDEC_BYTE_PROGRAM: - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - /* Truncate to emu_chip_size. */ - offs %= data->emu_chip_size; - if (writecnt < 5) { - msg_perr("BYTE PROGRAM size too short!\n"); - return 1; - } - if (writecnt - 4 > data->emu_max_byteprogram_size) { - msg_perr("Max BYTE PROGRAM size exceeded!\n"); - return 1; - } - memcpy(flashchip_contents + offs, writearr + 4, writecnt - 4); - data->emu_modified = 1; - break; - case JEDEC_BYTE_PROGRAM_4BA: - offs = writearr[1] << 24 | writearr[2] << 16 | writearr[3] << 8 | writearr[4]; - /* Truncate to emu_chip_size. */ - offs %= data->emu_chip_size; - if (writecnt < 6) { - msg_perr("BYTE PROGRAM size too short!\n"); - return 1; - } - if (writecnt - 5 > data->emu_max_byteprogram_size) { - msg_perr("Max BYTE PROGRAM size exceeded!\n"); - return 1; - } - memcpy(flashchip_contents + offs, writearr + 5, writecnt - 5); - data->emu_modified = 1; - break; - case JEDEC_AAI_WORD_PROGRAM: - if (!data->emu_max_aai_size) - break; - if (!(data->emu_status & SPI_SR_AAI)) { - if (writecnt < JEDEC_AAI_WORD_PROGRAM_OUTSIZE) { - msg_perr("Initial AAI WORD PROGRAM size too " - "short!\n"); - return 1; - } - if (writecnt > JEDEC_AAI_WORD_PROGRAM_OUTSIZE) { - msg_perr("Initial AAI WORD PROGRAM size too " - "long!\n"); - return 1; - } - data->emu_status |= SPI_SR_AAI; - aai_offs = writearr[1] << 16 | writearr[2] << 8 | - writearr[3]; - /* Truncate to emu_chip_size. */ - aai_offs %= data->emu_chip_size; - memcpy(flashchip_contents + aai_offs, writearr + 4, 2); - aai_offs += 2; - } else { - if (writecnt < JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) { - msg_perr("Continuation AAI WORD PROGRAM size " - "too short!\n"); - return 1; - } - if (writecnt > JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) { - msg_perr("Continuation AAI WORD PROGRAM size " - "too long!\n"); - return 1; - } - memcpy(flashchip_contents + aai_offs, writearr + 1, 2); - aai_offs += 2; - } - data->emu_modified = 1; - break; - case JEDEC_WRDI: - if (data->emu_max_aai_size) - data->emu_status &= ~SPI_SR_AAI; - break; - case JEDEC_SE: - if (!data->emu_jedec_se_size) - break; - if (writecnt != JEDEC_SE_OUTSIZE) { - msg_perr("SECTOR ERASE 0x20 outsize invalid!\n"); - return 1; - } - if (readcnt != JEDEC_SE_INSIZE) { - msg_perr("SECTOR ERASE 0x20 insize invalid!\n"); - return 1; - } - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - if (offs & (data->emu_jedec_se_size - 1)) - msg_pdbg("Unaligned SECTOR ERASE 0x20: 0x%x\n", offs); - offs &= ~(data->emu_jedec_se_size - 1); - memset(flashchip_contents + offs, 0xff, data->emu_jedec_se_size); - data->emu_modified = 1; - break; - case JEDEC_BE_52: - if (!data->emu_jedec_be_52_size) - break; - if (writecnt != JEDEC_BE_52_OUTSIZE) { - msg_perr("BLOCK ERASE 0x52 outsize invalid!\n"); - return 1; - } - if (readcnt != JEDEC_BE_52_INSIZE) { - msg_perr("BLOCK ERASE 0x52 insize invalid!\n"); - return 1; - } - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - if (offs & (data->emu_jedec_be_52_size - 1)) - msg_pdbg("Unaligned BLOCK ERASE 0x52: 0x%x\n", offs); - offs &= ~(data->emu_jedec_be_52_size - 1); - memset(flashchip_contents + offs, 0xff, data->emu_jedec_be_52_size); - data->emu_modified = 1; - break; - case JEDEC_BE_D8: - if (!data->emu_jedec_be_d8_size) - break; - if (writecnt != JEDEC_BE_D8_OUTSIZE) { - msg_perr("BLOCK ERASE 0xd8 outsize invalid!\n"); - return 1; - } - if (readcnt != JEDEC_BE_D8_INSIZE) { - msg_perr("BLOCK ERASE 0xd8 insize invalid!\n"); - return 1; - } - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - if (offs & (data->emu_jedec_be_d8_size - 1)) - msg_pdbg("Unaligned BLOCK ERASE 0xd8: 0x%x\n", offs); - offs &= ~(data->emu_jedec_be_d8_size - 1); - memset(flashchip_contents + offs, 0xff, data->emu_jedec_be_d8_size); - data->emu_modified = 1; - break; - case JEDEC_CE_60: - if (!data->emu_jedec_ce_60_size) - break; - if (writecnt != JEDEC_CE_60_OUTSIZE) { - msg_perr("CHIP ERASE 0x60 outsize invalid!\n"); - return 1; - } - if (readcnt != JEDEC_CE_60_INSIZE) { - msg_perr("CHIP ERASE 0x60 insize invalid!\n"); - return 1; - } - /* JEDEC_CE_60_OUTSIZE is 1 (no address) -> no offset. */ - /* emu_jedec_ce_60_size is emu_chip_size. */ - memset(flashchip_contents, 0xff, data->emu_jedec_ce_60_size); - data->emu_modified = 1; - break; - case JEDEC_CE_C7: - if (!data->emu_jedec_ce_c7_size) - break; - if (writecnt != JEDEC_CE_C7_OUTSIZE) { - msg_perr("CHIP ERASE 0xc7 outsize invalid!\n"); - return 1; - } - if (readcnt != JEDEC_CE_C7_INSIZE) { - msg_perr("CHIP ERASE 0xc7 insize invalid!\n"); - return 1; - } - /* JEDEC_CE_C7_OUTSIZE is 1 (no address) -> no offset. */ - /* emu_jedec_ce_c7_size is emu_chip_size. */ - memset(flashchip_contents, 0xff, data->emu_jedec_ce_c7_size); - data->emu_modified = 1; - break; - case JEDEC_SFDP: - if (data->emu_chip != EMULATE_MACRONIX_MX25L6436) - break; - if (writecnt < 4) - break; - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - - /* SFDP expects one dummy byte after the address. */ - if (writecnt == 4) { - /* The dummy byte was not written, make sure it is read instead. - * Shifting and shortening the read array does achieve this goal. - */ - readarr++; - readcnt--; - } else { - /* The response is shifted if more than 5 bytes are written, because SFDP data is - * already shifted out by the chip while those superfluous bytes are written. */ - offs += writecnt - 5; - } - - /* The SFDP spec implies that the start address of an SFDP read may be truncated to fit in the - * SFDP table address space, i.e. the start address may be wrapped around at SFDP table size. - * This is a reasonable implementation choice in hardware because it saves a few gates. */ - if (offs >= sizeof(sfdp_table)) { - msg_pdbg("Wrapping the start address around the SFDP table boundary (using 0x%x " - "instead of 0x%x).\n", (unsigned int)(offs % sizeof(sfdp_table)), offs); - offs %= sizeof(sfdp_table); - } - toread = min(sizeof(sfdp_table) - offs, readcnt); - memcpy(readarr, sfdp_table + offs, toread); - if (toread < readcnt) - msg_pdbg("Crossing the SFDP table boundary in a single " - "continuous chunk produces undefined results " - "after that point.\n"); - break; - default: - /* No special response. */ - break; - } - if (writearr[0] != JEDEC_WREN && writearr[0] != JEDEC_EWSR) - data->emu_status &= ~SPI_SR_WEL; - return 0; -} -#endif - -static struct emu_data* get_data_from_context(const struct flashctx *flash) -{ - if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH)) - return (struct emu_data *)flash->mst->par.data; - else if (dummy_buses_supported & BUS_SPI) - return (struct emu_data *)flash->mst->spi.data; - - return NULL; /* buses was set to BUS_NONE. */ -} - -static int dummy_spi_send_command(const struct flashctx *flash, unsigned int writecnt, - unsigned int readcnt, - const unsigned char *writearr, - unsigned char *readarr) -{ - unsigned int i; - struct emu_data *emu_data = get_data_from_context(flash); - if (!emu_data) { - msg_perr("No data in flash context!\n"); - return 1; - } - - msg_pspew("%s:", __func__); - - msg_pspew(" writing %u bytes:", writecnt); - for (i = 0; i < writecnt; i++) - msg_pspew(" 0x%02x", writearr[i]); - - /* Response for unknown commands and missing chip is 0xff. */ - memset(readarr, 0xff, readcnt); -#if EMULATE_SPI_CHIP - switch (emu_data->emu_chip) { - case EMULATE_ST_M25P10_RES: - case EMULATE_SST_SST25VF040_REMS: - case EMULATE_SST_SST25VF032B: - case EMULATE_MACRONIX_MX25L6436: - case EMULATE_WINBOND_W25Q128FV: - case EMULATE_VARIABLE_SIZE: - if (emulate_spi_chip_response(writecnt, readcnt, writearr, - readarr, emu_data)) { - msg_pdbg("Invalid command sent to flash chip!\n"); - return 1; - } - break; - default: - break; - } -#endif - msg_pspew(" reading %u bytes:", readcnt); - for (i = 0; i < readcnt; i++) - msg_pspew(" 0x%02x", readarr[i]); - msg_pspew("\n"); - - programmer_delay((writecnt + readcnt) * emu_data->delay_us); - return 0; -} - -static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) -{ - return spi_write_chunked(flash, buf, start, len, - spi_write_256_chunksize); -} - #if EMULATE_CHIP && EMULATE_SPI_CHIP int probe_variable_size(struct flashctx *flash) { -- To view, visit
https://review.coreboot.org/c/flashrom/+/50712
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: Ibfe9f556316ed509cbec522b4c9cb4c9041e5fdd Gerrit-Change-Number: 50712 Gerrit-PatchSet: 2 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-MessageType: merged
1
0
0
0
Change in flashrom[master]: tree: Remove forward-declarations for spi masters
by Angel Pons (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Nikolai Artemiev, Anastasia Klimchuk. Angel Pons has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50711
) Change subject: tree: Remove forward-declarations for spi masters ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50711
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I23ff6b79d794876f73b327f18784ca7c04c32c84 Gerrit-Change-Number: 50711 Gerrit-PatchSet: 2 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 09:36:54 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
Change in flashrom[master]: serprog.c: Remove forward-declarations
by Angel Pons (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Nikolai Artemiev, Anastasia Klimchuk. Angel Pons has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50713
) Change subject: serprog.c: Remove forward-declarations ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50713
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I6d05b2ad7b1a753aa752b22f9eb60a7b37dff641 Gerrit-Change-Number: 50713 Gerrit-PatchSet: 1 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 09:35:26 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
Change in flashrom[master]: dummyflasher.c: Remove forward-declarations
by Angel Pons (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Nikolai Artemiev, Anastasia Klimchuk. Angel Pons has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50712
) Change subject: dummyflasher.c: Remove forward-declarations ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50712
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: Ibfe9f556316ed509cbec522b4c9cb4c9041e5fdd Gerrit-Change-Number: 50712 Gerrit-PatchSet: 1 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 09:34:59 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
Change in flashrom[master]: tree: Remove forward-declarations for spi masters
by Sam McNally (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Nikolai Artemiev, Angel Pons, Anastasia Klimchuk. Sam McNally has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50711
) Change subject: tree: Remove forward-declarations for spi masters ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50711
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I23ff6b79d794876f73b327f18784ca7c04c32c84 Gerrit-Change-Number: 50711 Gerrit-PatchSet: 2 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-CC: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 02:13:54 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
Change in flashrom[master]: serprog.c: Remove forward-declarations
by Sam McNally (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Nikolai Artemiev, Angel Pons, Anastasia Klimchuk. Sam McNally has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50713
) Change subject: serprog.c: Remove forward-declarations ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50713
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I6d05b2ad7b1a753aa752b22f9eb60a7b37dff641 Gerrit-Change-Number: 50713 Gerrit-PatchSet: 1 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 02:13:53 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
Change in flashrom[master]: dummyflasher.c: Remove forward-declarations
by Sam McNally (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Nikolai Artemiev, Angel Pons, Anastasia Klimchuk. Sam McNally has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50712
) Change subject: dummyflasher.c: Remove forward-declarations ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50712
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: Ibfe9f556316ed509cbec522b4c9cb4c9041e5fdd Gerrit-Change-Number: 50712 Gerrit-PatchSet: 1 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 02:13:52 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
Change in flashrom[master]: serprog.c: Remove forward-declarations
by Edward O'Callaghan (Code Review)
16 Feb '21
16 Feb '21
Attention is currently required from: Sam McNally, Nikolai Artemiev, Angel Pons, Anastasia Klimchuk. Edward O'Callaghan has posted comments on this change. (
https://review.coreboot.org/c/flashrom/+/50713
) Change subject: serprog.c: Remove forward-declarations ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit
https://review.coreboot.org/c/flashrom/+/50713
To unsubscribe, or for help writing mail filters, visit
https://review.coreboot.org/settings
Gerrit-Project: flashrom Gerrit-Branch: master Gerrit-Change-Id: I6d05b2ad7b1a753aa752b22f9eb60a7b37dff641 Gerrit-Change-Number: 50713 Gerrit-PatchSet: 1 Gerrit-Owner: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Reviewer: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Reviewer: Edward O'Callaghan <quasisec(a)chromium.org> Gerrit-Reviewer: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Reviewer: Sam McNally <sammc(a)google.com> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-Attention: Sam McNally <sammc(a)google.com> Gerrit-Attention: Nikolai Artemiev <nartemiev(a)chromium.org> Gerrit-Attention: Angel Pons <th3fanbus(a)gmail.com> Gerrit-Attention: Anastasia Klimchuk <aklm(a)chromium.org> Gerrit-Comment-Date: Tue, 16 Feb 2021 00:28:41 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1
0
0
0
← Newer
1
...
5
6
7
8
9
10
11
...
16
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Results per page:
10
25
50
100
200