diff options
Diffstat (limited to 'internal.c')
-rw-r--r-- | internal.c | 320 |
1 files changed, 112 insertions, 208 deletions
diff --git a/internal.c b/internal.c index bdbe32d4d..faeb46354 100644 --- a/internal.c +++ b/internal.c @@ -16,176 +16,38 @@ #include <strings.h> #include <string.h> +#include <stdbool.h> #include <stdlib.h> + #include "flash.h" -#include "platform.h" #include "programmer.h" -#include "hwaccess.h" +#include "platform/pci.h" -int is_laptop = 0; -int laptop_ok = 0; +#if defined(__i386__) || defined(__x86_64__) +#include "hwaccess_x86_io.h" +#endif -int force_boardenable = 0; -int force_boardmismatch = 0; +bool force_boardmismatch = false; enum chipbustype internal_buses_supported = BUS_NONE; -struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass) -{ - struct pci_dev *temp; - struct pci_filter filter; - uint16_t tmp2; - - pci_filter_init(NULL, &filter); - filter.vendor = vendor; - - for (temp = pacc->devices; temp; temp = temp->next) - if (pci_filter_match(&filter, temp)) { - /* Read PCI class */ - tmp2 = pci_read_word(temp, 0x0a); - if (tmp2 == devclass) - return temp; - } - - return NULL; -} - -struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device) -{ - struct pci_dev *temp; - struct pci_filter filter; - - pci_filter_init(NULL, &filter); - filter.vendor = vendor; - filter.device = device; - - for (temp = pacc->devices; temp; temp = temp->next) - if (pci_filter_match(&filter, temp)) - return temp; - - return NULL; -} - -struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, - uint16_t card_vendor, uint16_t card_device) -{ - struct pci_dev *temp; - struct pci_filter filter; - - pci_filter_init(NULL, &filter); - filter.vendor = vendor; - filter.device = device; - - for (temp = pacc->devices; temp; temp = temp->next) - if (pci_filter_match(&filter, temp)) { - if ((card_vendor == - pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID)) - && (card_device == - pci_read_word(temp, PCI_SUBSYSTEM_ID))) - return temp; - } - - return NULL; -} - -#if IS_X86 -void probe_superio(void) -{ - probe_superio_winbond(); - /* ITE probe causes SMSC LPC47N217 to power off the serial UART. - * Always probe for SMSC first, and if a SMSC Super I/O is detected - * at a given I/O port, do _not_ probe that port with the ITE probe. - * This means SMSC probing must be done before ITE probing. - */ - //probe_superio_smsc(); - probe_superio_ite(); -} - -int superio_count = 0; -#define SUPERIO_MAX_COUNT 3 - -struct superio superios[SUPERIO_MAX_COUNT]; - -int register_superio(struct superio s) -{ - if (superio_count == SUPERIO_MAX_COUNT) - return 1; - superios[superio_count++] = s; - return 0; -} - -#endif /* IS_X86 */ - -static void internal_chip_writeb(const struct flashctx *flash, uint8_t val, - chipaddr addr) -{ - mmio_writeb(val, (void *) addr); -} -static void internal_chip_writew(const struct flashctx *flash, uint16_t val, - chipaddr addr) +static int get_params(const struct programmer_cfg *cfg, + bool *boardenable, bool *boardmismatch, + bool *force_laptop, bool *not_a_laptop, + char **board_vendor, char **board_model) { - mmio_writew(val, (void *) addr); -} - -static void internal_chip_writel(const struct flashctx *flash, uint32_t val, - chipaddr addr) -{ - mmio_writel(val, (void *) addr); -} - -static uint8_t internal_chip_readb(const struct flashctx *flash, - const chipaddr addr) -{ - return mmio_readb((void *) addr); -} - -static uint16_t internal_chip_readw(const struct flashctx *flash, - const chipaddr addr) -{ - return mmio_readw((void *) addr); -} - -static uint32_t internal_chip_readl(const struct flashctx *flash, - const chipaddr addr) -{ - return mmio_readl((void *) addr); -} - -static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf, - const chipaddr addr, size_t len) -{ - mmio_readn((void *)addr, buf, len); - return; -} - -static const struct par_master par_master_internal = { - .chip_readb = internal_chip_readb, - .chip_readw = internal_chip_readw, - .chip_readl = internal_chip_readl, - .chip_readn = internal_chip_readn, - .chip_writeb = internal_chip_writeb, - .chip_writew = internal_chip_writew, - .chip_writel = internal_chip_writel, - .chip_writen = fallback_chip_writen, -}; - -int internal_init(void) -{ - int ret = 0; - int force_laptop = 0; - int not_a_laptop = 0; - char *board_vendor = NULL; - char *board_model = NULL; -#if IS_X86 - const char *cb_vendor = NULL; - const char *cb_model = NULL; -#endif char *arg; - arg = extract_programmer_param("boardenable"); + /* default values. */ + *force_laptop = false; + *not_a_laptop = false; + *board_vendor = NULL; + *board_model = NULL; + + arg = extract_programmer_param_str(cfg, "boardenable"); if (arg && !strcmp(arg,"force")) { - force_boardenable = 1; + *boardenable = true; } else if (arg && !strlen(arg)) { msg_perr("Missing argument for boardenable.\n"); free(arg); @@ -197,9 +59,9 @@ int internal_init(void) } free(arg); - arg = extract_programmer_param("boardmismatch"); + arg = extract_programmer_param_str(cfg, "boardmismatch"); if (arg && !strcmp(arg,"force")) { - force_boardmismatch = 1; + *boardmismatch = true; } else if (arg && !strlen(arg)) { msg_perr("Missing argument for boardmismatch.\n"); free(arg); @@ -211,11 +73,11 @@ int internal_init(void) } free(arg); - arg = extract_programmer_param("laptop"); + arg = extract_programmer_param_str(cfg, "laptop"); if (arg && !strcmp(arg, "force_I_want_a_brick")) - force_laptop = 1; + *force_laptop = true; else if (arg && !strcmp(arg, "this_is_not_a_laptop")) - not_a_laptop = 1; + *not_a_laptop = true; else if (arg && !strlen(arg)) { msg_perr("Missing argument for laptop.\n"); free(arg); @@ -227,9 +89,9 @@ int internal_init(void) } free(arg); - arg = extract_programmer_param("mainboard"); + arg = extract_programmer_param_str(cfg, "mainboard"); if (arg && strlen(arg)) { - if (board_parse_parameter(arg, &board_vendor, &board_model)) { + if (board_parse_parameter(arg, board_vendor, board_model)) { free(arg); return 1; } @@ -240,10 +102,62 @@ int internal_init(void) } free(arg); - if (rget_io_perms()) { - ret = 1; - goto internal_init_exit; + return 0; +} + +static void report_nonwl_laptop_detected(const struct board_cfg *bcfg) +{ + const int is_laptop = bcfg->is_laptop; + const bool laptop_ok = bcfg->laptop_ok; + + if (!is_laptop || laptop_ok) + return; + + msg_pinfo("========================================================================\n"); + if (is_laptop == 1) { + msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n" + "internal buses have been disabled for safety reasons.\n\n"); + } else { + msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n" + "detect this for sure because your vendor has not set up the SMBIOS\n" + "tables correctly. Some internal buses have been disabled for\n" + "safety reasons. You can enforce using all buses by adding\n" + " -p internal:laptop=this_is_not_a_laptop\n" + "to the command line, but please read the following warning if you\n" + "are not sure.\n\n"); } + msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n" + "recommend to use the vendor flashing utility. The embedded controller\n" + "(EC) in these machines often interacts badly with flashing.\n" + "See the manpage and https://flashrom.org/Laptops for details.\n\n" + "If flash is shared with the EC, erase is guaranteed to brick your laptop\n" + "and write may brick your laptop.\n" + "Read and probe may irritate your EC and cause fan failure, backlight\n" + "failure and sudden poweroff.\n" + "You have been warned.\n" + "========================================================================\n"); +} + +static int internal_init(const struct programmer_cfg *cfg) +{ + int ret = 0; + bool force_laptop; + bool not_a_laptop; + char *board_vendor; + char *board_model; +#if defined(__i386__) || defined(__x86_64__) + const char *cb_vendor = NULL; + const char *cb_model = NULL; +#endif + bool force_boardenable = false; + struct board_cfg bcfg = {0}; + + ret = get_params(cfg, + &force_boardenable, &force_boardmismatch, + &force_laptop, ¬_a_laptop, + &board_vendor, &board_model); + if (ret) + return ret; /* Default to Parallel/LPC/FWH flash devices. If a known host controller * is found, the host controller init routine sets the @@ -251,7 +165,7 @@ int internal_init(void) */ internal_buses_supported = BUS_NONSPI; - if (try_mtd() == 0) { + if (try_mtd(cfg) == 0) { ret = 0; goto internal_init_exit; } @@ -269,7 +183,12 @@ int internal_init(void) goto internal_init_exit; } -#if IS_X86 +#if defined(__i386__) || defined(__x86_64__) + if (rget_io_perms()) { + ret = 1; + goto internal_init_exit; + } + if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) { if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) { msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n" @@ -283,12 +202,12 @@ int internal_init(void) } } - is_laptop = 2; /* Assume that we don't know by default. */ + bcfg.is_laptop = 2; /* Assume that we don't know by default. */ - dmi_init(); + dmi_init(&bcfg.is_laptop); /* In case Super I/O probing would cause pretty explosions. */ - board_handle_before_superio(); + board_handle_before_superio(&bcfg, force_boardenable); /* Probe for the Super I/O chip and fill global struct superio. */ probe_superio(); @@ -298,71 +217,49 @@ int internal_init(void) * FIXME: Find a replacement for DMI on non-x86. * FIXME: Enable Super I/O probing once port I/O is possible. */ -#endif /* IS_X86 */ +#endif /* Check laptop whitelist. */ - board_handle_before_laptop(); + board_handle_before_laptop(&bcfg, force_boardenable); /* * Disable all internal buses by default if we are not sure * this isn't a laptop. Board-enables may override this, * non-legacy buses (SPI and opaque atm) are probed anyway. */ - if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2))) + if (bcfg.is_laptop && !(bcfg.laptop_ok || force_laptop || (not_a_laptop && bcfg.is_laptop == 2))) internal_buses_supported = BUS_NONE; /* try to enable it. Failure IS an option, since not all motherboards * really need this to be done, etc., etc. */ - ret = chipset_flash_enable(); + struct programmer_cfg icfg = *cfg; + icfg.bcfg = &bcfg; + ret = chipset_flash_enable(&icfg); if (ret == -2) { msg_perr("WARNING: No chipset found. Flash detection " "will most likely fail.\n"); - } else if (ret == ERROR_FATAL) { + } else if (ret == ERROR_FLASHROM_FATAL) { goto internal_init_exit; } -#if IS_X86 +#if defined(__i386__) || defined(__x86_64__) /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */ - init_superio_ite(); + init_superio_ite(cfg); - if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) { + if (board_flash_enable(&bcfg, + board_vendor, board_model, cb_vendor, cb_model, force_boardenable)) { msg_perr("Aborting to be safe.\n"); ret = 1; goto internal_init_exit; } -#endif /* IS_X86 */ +#endif - if (internal_buses_supported & BUS_NONSPI) - register_par_master(&par_master_internal, internal_buses_supported); + internal_par_init(internal_buses_supported); /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */ - if (is_laptop && !laptop_ok) { - msg_pinfo("========================================================================\n"); - if (is_laptop == 1) { - msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n" - "internal buses have been disabled for safety reasons.\n\n"); - } else { - msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n" - "detect this for sure because your vendor has not set up the SMBIOS\n" - "tables correctly. Some internal buses have been disabled for\n" - "safety reasons. You can enforce using all buses by adding\n" - " -p internal:laptop=this_is_not_a_laptop\n" - "to the command line, but please read the following warning if you\n" - "are not sure.\n\n"); - } - msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n" - "recommend to use the vendor flashing utility. The embedded controller\n" - "(EC) in these machines often interacts badly with flashing.\n" - "See the manpage and https://flashrom.org/Laptops for details.\n\n" - "If flash is shared with the EC, erase is guaranteed to brick your laptop\n" - "and write may brick your laptop.\n" - "Read and probe may irritate your EC and cause fan failure, backlight\n" - "failure and sudden poweroff.\n" - "You have been warned.\n" - "========================================================================\n"); - } + report_nonwl_laptop_detected(&bcfg); ret = 0; @@ -372,3 +269,10 @@ internal_init_exit: return ret; } + +const struct programmer_entry programmer_internal = { + .name = "internal", + .type = OTHER, + .devs.note = NULL, + .init = internal_init, +}; |