summaryrefslogtreecommitdiffstats
path: root/internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'internal.c')
-rw-r--r--internal.c320
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, &not_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,
+};