1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-28 23:43:42 +02:00

serprog.c: Separate shutdown from failed init cleanup

Shutdown function was covering two different jobs here: 1) the actual
shutdown which is run at the end of the driver's lifecycle and
2) cleanup in cases when initialisation failed. Now, shutdown is only
doing its main job (#1), and the driver itself is doing cleanup
when init fails (#2).

The good thing is that now resources are released/closed immediately
in cases when init fails (vs shutdown function which was run at some
point later), and the driver leaves clean space after itself if init
fails.

And very importantly this unlocks API change which plans to move
register_shutdown inside register master API, see
https://review.coreboot.org/c/flashrom/+/51761

BUG=b:185191942
TEST=builds

Change-Id: Idf4ed62c19667e18cc807913180c48cb8c978805
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/54861
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
This commit is contained in:
Anastasia Klimchuk 2021-05-24 09:55:03 +10:00 committed by Edward O'Callaghan
parent ad8eb60e5d
commit e2f10684b7

View File

@ -635,33 +635,30 @@ int serprog_init(void)
return 1; return 1;
} }
if (register_shutdown(serprog_shutdown, NULL))
return 1;
msg_pdbg(MSGHEADER "connected - attempting to synchronize\n"); msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
sp_check_avail_automatic = 0; sp_check_avail_automatic = 0;
if (sp_synchronize()) if (sp_synchronize())
return 1; goto init_err_cleanup_exit;
msg_pdbg(MSGHEADER "Synchronized\n"); msg_pdbg(MSGHEADER "Synchronized\n");
if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) { if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
msg_perr("Error: NAK to query interface version\n"); msg_perr("Error: NAK to query interface version\n");
return 1; goto init_err_cleanup_exit;
} }
if (iface != 1) { if (iface != 1) {
msg_perr("Error: Unknown interface version: %d\n", iface); msg_perr("Error: Unknown interface version: %d\n", iface);
return 1; goto init_err_cleanup_exit;
} }
msg_pdbg(MSGHEADER "Interface version ok.\n"); msg_pdbg(MSGHEADER "Interface version ok.\n");
if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) { if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
msg_perr("Error: query command map not supported\n"); msg_perr("Error: query command map not supported\n");
return 1; goto init_err_cleanup_exit;
} }
sp_check_avail_automatic = 1; sp_check_avail_automatic = 1;
@ -688,10 +685,10 @@ int serprog_init(void)
if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) { if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
msg_perr("Error: SPI operation not supported while the " msg_perr("Error: SPI operation not supported while the "
"bustype is SPI\n"); "bustype is SPI\n");
return 1; goto init_err_cleanup_exit;
} }
if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL)) if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
return 1; goto init_err_cleanup_exit;
/* Success of any of these commands is optional. We don't need /* Success of any of these commands is optional. We don't need
the programmer to tell us its limits, but if it doesn't, we the programmer to tell us its limits, but if it doesn't, we
will assume stuff, so it's in the programmers best interest will assume stuff, so it's in the programmers best interest
@ -727,7 +724,7 @@ int serprog_init(void)
if (errno != 0 || spispeed == f_spi_suffix) { if (errno != 0 || spispeed == f_spi_suffix) {
msg_perr("Error: Could not convert 'spispeed'.\n"); msg_perr("Error: Could not convert 'spispeed'.\n");
free(spispeed); free(spispeed);
return 1; goto init_err_cleanup_exit;
} }
if (strlen(f_spi_suffix) == 1) { if (strlen(f_spi_suffix) == 1) {
if (!strcasecmp(f_spi_suffix, "M")) if (!strcasecmp(f_spi_suffix, "M"))
@ -737,12 +734,12 @@ int serprog_init(void)
else { else {
msg_perr("Error: Garbage following 'spispeed' value.\n"); msg_perr("Error: Garbage following 'spispeed' value.\n");
free(spispeed); free(spispeed);
return 1; goto init_err_cleanup_exit;
} }
} else if (strlen(f_spi_suffix) > 1) { } else if (strlen(f_spi_suffix) > 1) {
msg_perr("Error: Garbage following 'spispeed' value.\n"); msg_perr("Error: Garbage following 'spispeed' value.\n");
free(spispeed); free(spispeed);
return 1; goto init_err_cleanup_exit;
} }
buf[0] = (f_spi_req >> (0 * 8)) & 0xFF; buf[0] = (f_spi_req >> (0 * 8)) & 0xFF;
@ -765,38 +762,38 @@ int serprog_init(void)
free(spispeed); free(spispeed);
bt = serprog_buses_supported; bt = serprog_buses_supported;
if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL)) if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
return 1; goto init_err_cleanup_exit;
} }
if (serprog_buses_supported & BUS_NONSPI) { if (serprog_buses_supported & BUS_NONSPI) {
if (sp_check_commandavail(S_CMD_O_INIT) == 0) { if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
msg_perr("Error: Initialize operation buffer " msg_perr("Error: Initialize operation buffer "
"not supported\n"); "not supported\n");
return 1; goto init_err_cleanup_exit;
} }
if (sp_check_commandavail(S_CMD_O_DELAY) == 0) { if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
msg_perr("Error: Write to opbuf: " msg_perr("Error: Write to opbuf: "
"delay not supported\n"); "delay not supported\n");
return 1; goto init_err_cleanup_exit;
} }
/* S_CMD_O_EXEC availability checked later. */ /* S_CMD_O_EXEC availability checked later. */
if (sp_check_commandavail(S_CMD_R_BYTE) == 0) { if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
msg_perr("Error: Single byte read not supported\n"); msg_perr("Error: Single byte read not supported\n");
return 1; goto init_err_cleanup_exit;
} }
/* This could be translated to single byte reads (if missing), /* This could be translated to single byte reads (if missing),
* but now we don't support that. */ * but now we don't support that. */
if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) { if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
msg_perr("Error: Read n bytes not supported\n"); msg_perr("Error: Read n bytes not supported\n");
return 1; goto init_err_cleanup_exit;
} }
if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) { if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
msg_perr("Error: Write to opbuf: " msg_perr("Error: Write to opbuf: "
"write byte not supported\n"); "write byte not supported\n");
return 1; goto init_err_cleanup_exit;
} }
if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) { if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
@ -815,7 +812,7 @@ int serprog_init(void)
if (!sp_write_n_buf) { if (!sp_write_n_buf) {
msg_perr("Error: cannot allocate memory for " msg_perr("Error: cannot allocate memory for "
"Write-n buffer\n"); "Write-n buffer\n");
return 1; goto init_err_cleanup_exit;
} }
sp_write_n_bytes = 0; sp_write_n_bytes = 0;
} }
@ -853,12 +850,12 @@ int serprog_init(void)
if (sp_check_commandavail(S_CMD_O_EXEC) == 0) { if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
msg_perr("Error: Execute operation buffer not " msg_perr("Error: Execute operation buffer not "
"supported\n"); "supported\n");
return 1; goto init_err_cleanup_exit;
} }
if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) { if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
msg_perr("Error: NAK to initialize operation buffer\n"); msg_perr("Error: NAK to initialize operation buffer\n");
return 1; goto init_err_cleanup_exit;
} }
if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2, if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2,
@ -873,20 +870,28 @@ int serprog_init(void)
uint8_t en = 1; uint8_t en = 1;
if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) { if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) {
msg_perr("Error: could not enable output buffers\n"); msg_perr("Error: could not enable output buffers\n");
return 1; goto init_err_cleanup_exit;
} else } else
msg_pdbg(MSGHEADER "Output drivers enabled\n"); msg_pdbg(MSGHEADER "Output drivers enabled\n");
} else } else
msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n"); msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n");
sp_prev_was_write = 0; sp_prev_was_write = 0;
sp_streamed_transmit_ops = 0; sp_streamed_transmit_ops = 0;
sp_streamed_transmit_bytes = 0; sp_streamed_transmit_bytes = 0;
sp_opbuf_usage = 0; sp_opbuf_usage = 0;
if (register_shutdown(serprog_shutdown, NULL))
goto init_err_cleanup_exit;
if (serprog_buses_supported & BUS_SPI) if (serprog_buses_supported & BUS_SPI)
register_spi_master(&spi_master_serprog, NULL); register_spi_master(&spi_master_serprog, NULL);
if (serprog_buses_supported & BUS_NONSPI) if (serprog_buses_supported & BUS_NONSPI)
register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI, NULL); register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI, NULL);
return 0; return 0;
init_err_cleanup_exit:
serprog_shutdown(NULL);
return 1;
} }
void serprog_delay(unsigned int usecs) void serprog_delay(unsigned int usecs)