summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/chipdrivers.h181
-rw-r--r--include/cli_classic.h43
-rw-r--r--include/coreboot_tables.h146
-rw-r--r--include/custom_baud.h37
-rw-r--r--include/edi.h30
-rw-r--r--include/ene.h51
-rw-r--r--include/erasure_layout.h41
-rw-r--r--include/flash.h702
-rw-r--r--include/flashchips.h1055
-rw-r--r--include/fmap.h71
-rw-r--r--include/hwaccess_physmap.h59
-rw-r--r--include/hwaccess_x86_io.h37
-rw-r--r--include/hwaccess_x86_msr.h28
-rw-r--r--include/i2c_helper.h131
-rw-r--r--include/ich_descriptors.h596
-rw-r--r--include/layout.h78
-rw-r--r--include/libflashrom.h598
-rw-r--r--include/platform.h64
-rw-r--r--include/platform/pci.h31
-rw-r--r--include/platform/swap.h80
-rw-r--r--include/programmer.h538
-rw-r--r--include/spi.h240
-rw-r--r--include/usb_device.h181
-rw-r--r--include/writeprotect.h98
24 files changed, 5116 insertions, 0 deletions
diff --git a/include/chipdrivers.h b/include/chipdrivers.h
new file mode 100644
index 000000000..a2e75d1a5
--- /dev/null
+++ b/include/chipdrivers.h
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Header file for flash chip drivers. Included from flash.h.
+ * As a general rule, every function listed here should take a pointer to
+ * struct flashctx as first parameter.
+ */
+
+#ifndef __CHIPDRIVERS_H__
+#define __CHIPDRIVERS_H__ 1
+
+#include "flash.h" /* for chipaddr and flashctx */
+
+/* spi.c */
+int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int spi_chip_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, int unsigned len);
+bool spi_probe_opcode(const struct flashctx *flash, uint8_t opcode);
+
+/* spi25.c */
+int probe_spi_rdid(struct flashctx *flash);
+int probe_spi_rdid4(struct flashctx *flash);
+int probe_spi_rems(struct flashctx *flash);
+int probe_spi_res1(struct flashctx *flash);
+int probe_spi_res2(struct flashctx *flash);
+int probe_spi_res3(struct flashctx *flash);
+int probe_spi_at25f(struct flashctx *flash);
+int spi_write_enable(struct flashctx *flash);
+int spi_write_disable(struct flashctx *flash);
+int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_21(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_52(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_53(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_5c(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+enum block_erase_func spi25_get_erasefn_from_opcode(uint8_t opcode);
+const uint8_t *spi_get_opcode_from_erasefn(enum block_erase_func func);
+int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
+int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
+int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
+int spi_enter_4ba(struct flashctx *flash);
+int spi_exit_4ba(struct flashctx *flash);
+int spi_set_extended_address(struct flashctx *, uint8_t addr_high);
+
+
+/* spi25_statusreg.c */
+int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value);
+int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t value);
+void spi_prettyprint_status_register_bit(uint8_t status, int bit);
+
+/* sfdp.c */
+int probe_spi_sfdp(struct flashctx *flash);
+
+/* opaque.c */
+int probe_opaque(struct flashctx *flash);
+int read_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int write_opaque(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int erase_opaque(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
+
+/* at45db.c */
+int probe_spi_at45db(struct flashctx *flash);
+int spi_prettyprint_status_register_at45db(struct flashctx *flash);
+int spi_disable_blockprotect_at45db(struct flashctx *flash);
+int spi_read_at45db(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int spi_read_at45db_e8(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int spi_write_at45db(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int spi_erase_at45db_page(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_erase_at45db_block(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_erase_at45db_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_erase_at45db_chip(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int spi_erase_at45cs_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+
+/* 82802ab.c */
+uint8_t wait_82802ab(struct flashctx *flash);
+int probe_82802ab(struct flashctx *flash);
+int erase_block_82802ab(struct flashctx *flash, unsigned int page, unsigned int pagesize);
+int write_82802ab(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+void print_status_82802ab(uint8_t status);
+blockprotect_func_t *lookup_82802ab_blockprotect_func_ptr(const struct flashchip *const chip);
+
+/* jedec.c */
+uint8_t oddparity(uint8_t val);
+void toggle_ready_jedec(const struct flashctx *flash, chipaddr dst);
+void data_polling_jedec(const struct flashctx *flash, chipaddr dst, uint8_t data);
+int probe_jedec(struct flashctx *flash);
+int probe_jedec_29gl(struct flashctx *flash);
+int write_jedec(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int write_jedec_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int erase_sector_jedec(struct flashctx *flash, unsigned int page, unsigned int pagesize);
+int erase_block_jedec(struct flashctx *flash, unsigned int page, unsigned int blocksize);
+int erase_chip_block_jedec(struct flashctx *flash, unsigned int page, unsigned int blocksize);
+
+blockprotect_func_t *lookup_jedec_blockprotect_func_ptr(const struct flashchip *const chip);
+int printlock_regspace2_uniform_64k(struct flashctx *flash);
+int printlock_regspace2_block_eraser_0(struct flashctx *flash);
+int printlock_regspace2_block_eraser_1(struct flashctx *flash);
+
+/* sst28sf040.c */
+int erase_chip_28sf040(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int erase_sector_28sf040(struct flashctx *flash, unsigned int address, unsigned int sector_size);
+int write_28sf040(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int unprotect_28sf040(struct flashctx *flash);
+int protect_28sf040(struct flashctx *flash);
+
+/* sst49lfxxxc.c */
+int erase_sector_49lfxxxc(struct flashctx *flash, unsigned int address, unsigned int sector_size);
+
+/* sst_fwhub.c */
+int printlock_sst_fwhub(struct flashctx *flash);
+int unlock_sst_fwhub(struct flashctx *flash);
+
+/* s25f.c */
+int probe_spi_big_spansion(struct flashctx *flash);
+int s25fl_block_erase(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+int s25fs_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+
+/* w39.c */
+int printlock_w39f010(struct flashctx * flash);
+int printlock_w39l010(struct flashctx * flash);
+int printlock_w39l020(struct flashctx * flash);
+int printlock_w39l040(struct flashctx * flash);
+int printlock_w39v040a(struct flashctx *flash);
+int printlock_w39v040b(struct flashctx *flash);
+int printlock_w39v040c(struct flashctx *flash);
+int printlock_w39v040fa(struct flashctx *flash);
+int printlock_w39v040fb(struct flashctx *flash);
+int printlock_w39v040fc(struct flashctx *flash);
+int printlock_w39v080a(struct flashctx *flash);
+int printlock_w39v080fa(struct flashctx *flash);
+int printlock_w39v080fa_dual(struct flashctx *flash);
+int printlock_at49f(struct flashctx *flash);
+
+/* w29ee011.c */
+int probe_w29ee011(struct flashctx *flash);
+bool w29ee011_can_override(const char *const chip_name, const char *const override_chip);
+
+/* stm50.c */
+int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int blocksize);
+
+/* en29lv640b.c */
+int probe_en29lv640b(struct flashctx *flash);
+int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+
+/* edi.c */
+int edi_chip_block_erase(struct flashctx *flash, unsigned int page, unsigned int size);
+int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int edi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int edi_probe_kb9012(struct flashctx *flash);
+
+/* spi95.c */
+int probe_spi_st95(struct flashctx *flash);
+int spi_block_erase_emulation(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+
+/* writeprotect_ranges.c */
+void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
+void decode_range_spi25_64k_block(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
+void decode_range_spi25_bit_cmp(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
+void decode_range_spi25_2x_block(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
+
+#endif /* !__CHIPDRIVERS_H__ */
diff --git a/include/cli_classic.h b/include/cli_classic.h
new file mode 100644
index 000000000..e651cc636
--- /dev/null
+++ b/include/cli_classic.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef CLI_CLASSIC_H
+#define CLI_CLASSIC_H
+
+#if __has_include(<getopt.h>)
+#include <getopt.h>
+#else
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+struct option {
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+int getopt (int argc, char *const *argv, const char *shortopts);
+int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+int getopt_long_only (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+
+#endif /* __has_include() */
+#endif /* CLI_CLASSIC_H */
diff --git a/include/coreboot_tables.h b/include/coreboot_tables.h
new file mode 100644
index 000000000..e1f63a81d
--- /dev/null
+++ b/include/coreboot_tables.h
@@ -0,0 +1,146 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2002 Linux Networx
+ * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
+ * Copyright (C) 2005-2007 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef COREBOOT_TABLES_H
+#define COREBOOT_TABLES_H
+
+#include <stdint.h>
+
+/* The coreboot table information is for conveying information
+ * from the firmware to the loaded OS image. Primarily this
+ * is expected to be information that cannot be discovered by
+ * other means, such as querying the hardware directly.
+ *
+ * All of the information should be Position Independent Data.
+ * That is it should be safe to relocated any of the information
+ * without it's meaning/correctness changing. For table that
+ * can reasonably be used on multiple architectures the data
+ * size should be fixed. This should ease the transition between
+ * 32 bit and 64 bit architectures etc.
+ *
+ * The completeness test for the information in this table is:
+ * - Can all of the hardware be detected?
+ * - Are the per motherboard constants available?
+ * - Is there enough to allow a kernel to run that was written before
+ * a particular motherboard is constructed? (Assuming the kernel
+ * has drivers for all of the hardware but it does not have
+ * assumptions on how the hardware is connected together).
+ *
+ * With this test it should be straight forward to determine if a
+ * table entry is required or not. This should remove much of the
+ * long term compatibility burden as table entries which are
+ * irrelevant or have been replaced by better alternatives may be
+ * dropped. Of course it is polite and expedite to include extra
+ * table entries and be backwards compatible, but it is not required.
+ */
+
+/* Since coreboot is usually compiled 32bit, gcc will align 64bit
+ * types to 32bit boundaries. If the coreboot table is dumped on a
+ * 64bit system, a uint64_t would be aligned to 64bit boundaries,
+ * breaking the table format.
+ *
+ * lb_uint64 will keep 64bit coreboot table values aligned to 32bit
+ * to ensure compatibility. They can be accessed with the two functions
+ * below: unpack_lb64() and pack_lb64()
+ *
+ * See also: util/lbtdump/lbtdump.c
+ */
+
+struct lb_uint64 {
+ uint32_t lo;
+ uint32_t hi;
+};
+
+struct lb_header {
+ uint8_t signature[4]; /* LBIO */
+ uint32_t header_bytes;
+ uint32_t header_checksum;
+ uint32_t table_bytes;
+ uint32_t table_checksum;
+ uint32_t table_entries;
+};
+
+/* Every entry in the boot environment list will correspond to a boot
+ * info record. Encoding both type and size. The type is obviously
+ * so you can tell what it is. The size allows you to skip that
+ * boot environment record if you don't know what it easy. This allows
+ * forward compatibility with records not yet defined.
+ */
+struct lb_record {
+ uint32_t tag; /* tag ID */
+ uint32_t size; /* size of record (in bytes) */
+};
+
+#define LB_TAG_UNUSED 0x0000
+
+#define LB_TAG_MEMORY 0x0001
+
+struct lb_memory_range {
+ struct lb_uint64 start;
+ struct lb_uint64 size;
+ uint32_t type;
+#define LB_MEM_RAM 1 /* Memory anyone can use */
+#define LB_MEM_RESERVED 2 /* Don't use this memory region */
+#define LB_MEM_TABLE 16 /* Ram configuration tables are kept in */
+};
+
+struct lb_memory {
+ uint32_t tag;
+ uint32_t size;
+ struct lb_memory_range map[0];
+};
+
+#define LB_TAG_HWRPB 0x0002
+struct lb_hwrpb {
+ uint32_t tag;
+ uint32_t size;
+ uint64_t hwrpb;
+};
+
+#define LB_TAG_MAINBOARD 0x0003
+struct lb_mainboard {
+ uint32_t tag;
+ uint32_t size;
+ uint8_t vendor_idx;
+ uint8_t part_number_idx;
+ uint8_t strings[0];
+};
+
+#define LB_TAG_VERSION 0x0004
+#define LB_TAG_EXTRA_VERSION 0x0005
+#define LB_TAG_BUILD 0x0006
+#define LB_TAG_COMPILE_TIME 0x0007
+#define LB_TAG_COMPILE_BY 0x0008
+#define LB_TAG_COMPILE_HOST 0x0009
+#define LB_TAG_COMPILE_DOMAIN 0x000a
+#define LB_TAG_COMPILER 0x000b
+#define LB_TAG_LINKER 0x000c
+#define LB_TAG_ASSEMBLER 0x000d
+struct lb_string {
+ uint32_t tag;
+ uint32_t size;
+ uint8_t string[0];
+};
+
+#define LB_TAG_FORWARD 0x0011
+struct lb_forward {
+ uint32_t tag;
+ uint32_t size;
+ uint64_t forward;
+};
+
+#endif /* COREBOOT_TABLES_H */
diff --git a/include/custom_baud.h b/include/custom_baud.h
new file mode 100644
index 000000000..38e6cfc40
--- /dev/null
+++ b/include/custom_baud.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2017 Urja Rannikko <urjaman@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CUSTOM_BAUD_H__
+#define __CUSTOM_BAUD_H__ 1
+
+struct baudentry {
+ int flag;
+ unsigned int baud;
+};
+
+enum custom_baud_stage {
+ BEFORE_FLAGS = 0,
+ WITH_FLAGS,
+ AFTER_FLAGS
+};
+
+int set_custom_baudrate(int fd, unsigned int baud, const enum custom_baud_stage stage, void *tio_wanted);
+
+/* Returns 1 if non-exact rate would be used, and setting a custom rate is supported.
+ The baudtable must be in ascending order and terminated with a 0-baud entry. */
+int use_custom_baud(unsigned int baud, const struct baudentry *baudtable);
+
+#endif
diff --git a/include/edi.h b/include/edi.h
new file mode 100644
index 000000000..542bf26ec
--- /dev/null
+++ b/include/edi.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2015 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __EDI_H__
+#define __EDI_H__ 1
+
+#define EDI_READ 0x30
+#define EDI_WRITE 0x40
+#define EDI_DISABLE 0xf3
+
+#define EDI_NOT_READY 0x5f
+#define EDI_READY 0x50
+
+#define EDI_READ_BUFFER_LENGTH_DEFAULT 3
+#define EDI_READ_BUFFER_LENGTH_MAX 32
+
+#endif
diff --git a/include/ene.h b/include/ene.h
new file mode 100644
index 000000000..e03e49b2e
--- /dev/null
+++ b/include/ene.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2015 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ENE_H__
+#define __ENE_H__ 1
+
+#define ENE_XBI_EFA0 0xfea8
+#define ENE_XBI_EFA1 0xfea9
+#define ENE_XBI_EFA2 0xfeaa
+#define ENE_XBI_EFDAT 0xfeab
+#define ENE_XBI_EFCMD 0xfeac
+#define ENE_XBI_EFCFG 0xfead
+
+#define ENE_XBI_EFCFG_CMD_WE (1 << 3)
+#define ENE_XBI_EFCFG_BUSY (1 << 1)
+
+#define ENE_XBI_EFCMD_HVPL_LATCH 0x02
+#define ENE_XBI_EFCMD_READ 0x03
+#define ENE_XBI_EFCMD_ERASE 0x20
+#define ENE_XBI_EFCMD_PROGRAM 0x70
+#define ENE_XBI_EFCMD_HVPL_CLEAR 0x80
+
+#define ENE_EC_PXCFG 0xff14
+
+#define ENE_EC_PXCFG_8051_RESET 0x01
+
+#define ENE_EC_HWVERSION 0xff00
+#define ENE_EC_EDIID 0xff24
+
+#define ENE_KB9012_HWVERSION 0xc3
+#define ENE_KB9012_EDIID 0x04
+
+struct ene_chip {
+ unsigned char hwversion;
+ unsigned char ediid;
+};
+
+#endif
diff --git a/include/erasure_layout.h b/include/erasure_layout.h
new file mode 100644
index 000000000..b8b5f089a
--- /dev/null
+++ b/include/erasure_layout.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2022 Aarya Chaumal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ERASURE_LAYOUT_H__
+#define __ERASURE_LAYOUT_H__ 1
+
+struct eraseblock_data {
+ chipoff_t start_addr;
+ chipoff_t end_addr;
+ bool selected;
+ size_t block_num;
+ size_t first_sub_block_index;
+ size_t last_sub_block_index;
+};
+
+struct erase_layout {
+ struct eraseblock_data* layout_list;
+ size_t block_count;
+ const struct block_eraser *eraser;
+};
+
+void free_erase_layout(struct erase_layout *layout, unsigned int erasefn_count);
+int create_erase_layout(struct flashctx *const flashctx, struct erase_layout **erase_layout);
+int erase_write(struct flashctx *const flashctx, chipoff_t region_start, chipoff_t region_end,
+ uint8_t* curcontents, uint8_t* newcontents,
+ struct erase_layout *erase_layout, bool *all_skipped);
+
+#endif /* !__ERASURE_LAYOUT_H__ */
diff --git a/include/flash.h b/include/flash.h
new file mode 100644
index 000000000..4c08549bc
--- /dev/null
+++ b/include/flash.h
@@ -0,0 +1,702 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2000 Silicon Integrated System Corporation
+ * Copyright (C) 2000 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2005-2009 coresystems GmbH
+ * Copyright (C) 2006-2009 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __FLASH_H__
+#define __FLASH_H__ 1
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#if IS_WINDOWS
+#include <windows.h>
+#undef min
+#undef max
+#endif
+
+#include "libflashrom.h"
+#include "layout.h"
+#include "writeprotect.h"
+
+#define KiB (1024)
+#define MiB (1024 * KiB)
+
+#define BIT(x) (1<<(x))
+
+/* Assumes `n` and `a` are at most 64-bit wide (to avoid typeof() operator). */
+#define ALIGN_DOWN(n, a) ((n) & ~((uint64_t)(a) - 1))
+
+#define ERROR_PTR ((void*)-1)
+
+/* Error codes */
+#define ERROR_OOM -100
+#define TIMEOUT_ERROR -101
+
+/* TODO: check using code for correct usage of types */
+typedef uintptr_t chipaddr;
+#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))
+
+int register_shutdown(int (*function) (void *data), void *data);
+struct registered_master;
+void *master_map_flash_region(const struct registered_master *mast,
+ const char *descr, uintptr_t phys_addr, size_t len);
+void master_unmap_flash_region(const struct registered_master *mast,
+ void *virt_addr, size_t len);
+/* NOTE: flashctx is not used in default_delay. In this case, a context should be NULL. */
+void programmer_delay(const struct flashrom_flashctx *flash, unsigned int usecs);
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+enum chipbustype {
+ BUS_NONE = 0,
+ BUS_PARALLEL = 1 << 0,
+ BUS_LPC = 1 << 1,
+ BUS_FWH = 1 << 2,
+ BUS_SPI = 1 << 3,
+ BUS_PROG = 1 << 4,
+ BUS_NONSPI = BUS_PARALLEL | BUS_LPC | BUS_FWH,
+};
+
+/*
+ * The following enum defines possible write granularities of flash chips. These tend to reflect the properties
+ * of the actual hardware not necessarily the write function(s) defined by the respective struct flashchip.
+ * The latter might (and should) be more precisely specified, e.g. they might bail out early if their execution
+ * would result in undefined chip contents.
+ */
+enum write_granularity {
+ /* We assume 256 byte granularity by default. */
+ WRITE_GRAN_256BYTES = 0,/* If less than 256 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_1BIT, /* Each bit can be cleared individually. */
+ WRITE_GRAN_1BYTE, /* A byte can be written once. Further writes to an already written byte cause
+ * its contents to be either undefined or to stay unchanged. */
+ WRITE_GRAN_128BYTES, /* If less than 128 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_264BYTES, /* If less than 264 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_512BYTES, /* If less than 512 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_528BYTES, /* If less than 528 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_1024BYTES, /* If less than 1024 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_1056BYTES, /* If less than 1056 bytes are written, the unwritten bytes are undefined. */
+ WRITE_GRAN_1BYTE_IMPLICIT_ERASE, /* EEPROMs and other chips with implicit erase and 1-byte writes. */
+};
+
+/*
+ * How many different contiguous runs of erase blocks with one size each do
+ * we have for a given erase function?
+ */
+#define NUM_ERASEREGIONS 5
+
+/*
+ * How many different erase functions do we have per chip?
+ * Macronix MX25L25635F has 8 different functions.
+ */
+#define NUM_ERASEFUNCTIONS 8
+
+#define MAX_CHIP_RESTORE_FUNCTIONS 4
+
+/* Feature bits used for non-SPI only */
+#define FEATURE_REGISTERMAP (1 << 0)
+#define FEATURE_LONG_RESET (0 << 4)
+#define FEATURE_SHORT_RESET (1 << 4)
+#define FEATURE_EITHER_RESET FEATURE_LONG_RESET
+#define FEATURE_RESET_MASK (FEATURE_LONG_RESET | FEATURE_SHORT_RESET)
+#define FEATURE_ADDR_FULL (0 << 2)
+#define FEATURE_ADDR_MASK (3 << 2)
+#define FEATURE_ADDR_2AA (1 << 2)
+#define FEATURE_ADDR_AAA (2 << 2)
+#define FEATURE_ADDR_SHIFTED (1 << 5)
+/* Feature bits used for SPI only */
+#define FEATURE_WRSR_EWSR (1 << 6)
+#define FEATURE_WRSR_WREN (1 << 7)
+#define FEATURE_WRSR_EITHER (FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
+#define FEATURE_OTP (1 << 8)
+#define FEATURE_QPI (1 << 9)
+#define FEATURE_4BA_ENTER (1 << 10) /**< Can enter/exit 4BA mode with instructions 0xb7/0xe9 w/o WREN */
+#define FEATURE_4BA_ENTER_WREN (1 << 11) /**< Can enter/exit 4BA mode with instructions 0xb7/0xe9 after WREN */
+#define FEATURE_4BA_ENTER_EAR7 (1 << 12) /**< Can enter/exit 4BA mode by setting bit7 of the ext addr reg */
+#define FEATURE_4BA_EAR_C5C8 (1 << 13) /**< Regular 3-byte operations can be used by writing the most
+ significant address byte into an extended address register
+ (using 0xc5/0xc8 instructions). */
+#define FEATURE_4BA_EAR_1716 (1 << 14) /**< Like FEATURE_4BA_EAR_C5C8 but with 0x17/0x16 instructions. */
+#define FEATURE_4BA_READ (1 << 15) /**< Native 4BA read instruction (0x13) is supported. */
+#define FEATURE_4BA_FAST_READ (1 << 16) /**< Native 4BA fast read instruction (0x0c) is supported. */
+#define FEATURE_4BA_WRITE (1 << 17) /**< Native 4BA byte program (0x12) is supported. */
+/* 4BA Shorthands */
+#define FEATURE_4BA_EAR_ANY (FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_EAR_1716)
+#define FEATURE_4BA_NATIVE (FEATURE_4BA_READ | FEATURE_4BA_FAST_READ | FEATURE_4BA_WRITE)
+#define FEATURE_4BA (FEATURE_4BA_ENTER | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_NATIVE)
+#define FEATURE_4BA_WREN (FEATURE_4BA_ENTER_WREN | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_NATIVE)
+#define FEATURE_4BA_EAR7 (FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_NATIVE)
+/*
+ * Most flash chips are erased to ones and programmed to zeros. However, some
+ * other flash chips, such as the ENE KB9012 internal flash, work the opposite way.
+ */
+#define FEATURE_ERASED_ZERO (1 << 18)
+#define FEATURE_NO_ERASE (1 << 19)
+
+#define FEATURE_WRSR_EXT2 (1 << 20)
+#define FEATURE_WRSR2 (1 << 21)
+#define FEATURE_WRSR_EXT3 ((1 << 22) | FEATURE_WRSR_EXT2)
+#define FEATURE_WRSR3 (1 << 23)
+
+/*
+ * Whether chip has security register (RDSCUR/WRSCUR commands).
+ * Not to be confused with "secure registers" of OTP.
+ */
+#define FEATURE_SCUR (1 << 24)
+
+/* Whether chip has configuration register (RDCR/WRSR_EXT2 commands) */
+#define FEATURE_CFGR (1 << 25)
+
+#define ERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff)
+#define UNERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0xff : 0x00)
+
+enum test_state {
+ OK = 0,
+ NT = 1, /* Not tested */
+ BAD, /* Known to not work */
+ DEP, /* Support depends on configuration (e.g. Intel flash descriptor) */
+ NA, /* Not applicable (e.g. write support on ROM chips) */
+};
+
+#define TEST_UNTESTED (struct tested){ .probe = NT, .read = NT, .erase = NT, .write = NT, .wp = NT }
+
+#define TEST_OK_PROBE (struct tested){ .probe = OK, .read = NT, .erase = NT, .write = NT, .wp = NT }
+#define TEST_OK_PR (struct tested){ .probe = OK, .read = OK, .erase = NT, .write = NT, .wp = NT }
+#define TEST_OK_PRE (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = NT, .wp = NT }
+#define TEST_OK_PREW (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = OK, .wp = NT }
+#define TEST_OK_PREWB (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = OK, .wp = OK }
+
+#define TEST_BAD_PROBE (struct tested){ .probe = BAD, .read = NT, .erase = NT, .write = NT, .wp = NT }
+#define TEST_BAD_PR (struct tested){ .probe = BAD, .read = BAD, .erase = NT, .write = NT, .wp = NT }
+#define TEST_BAD_PRE (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = NT, .wp = NT }
+#define TEST_BAD_PREW (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = BAD, .wp = NT }
+#define TEST_BAD_PREWB (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = BAD, .wp = BAD }
+
+struct flashrom_flashctx;
+#define flashctx flashrom_flashctx /* TODO: Agree on a name and convert all occurrences. */
+typedef int (erasefunc_t)(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
+
+enum flash_reg {
+ INVALID_REG = 0,
+ STATUS1,
+ STATUS2,
+ STATUS3,
+ SECURITY,
+ CONFIG,
+ MAX_REGISTERS
+};
+
+struct reg_bit_info {
+ /* Register containing the bit */
+ enum flash_reg reg;
+
+ /* Bit index within register */
+ uint8_t bit_index;
+
+ /*
+ * Writability of the bit. RW does not guarantee the bit will be
+ * writable, for example if status register protection is enabled.
+ */
+ enum {
+ RO, /* Read only */
+ RW, /* Readable and writable */
+ OTP /* One-time programmable */
+ } writability;
+};
+
+struct wp_bits;
+
+enum decode_range_func {
+ NO_DECODE_RANGE_FUNC = 0, /* 0 indicates no range decode function is set. */
+ DECODE_RANGE_SPI25 = 1,
+ DECODE_RANGE_SPI25_64K_BLOCK = 2,
+ DECODE_RANGE_SPI25_BIT_CMP = 3,
+ DECODE_RANGE_SPI25_2X_BLOCK = 4,
+};
+typedef void (decode_range_func_t)(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
+
+enum probe_func {
+ NO_PROBE_FUNC = 0, /* 0 indicates no probe function set. */
+ PROBE_JEDEC = 1,
+ PROBE_JEDEC_29GL,
+ PROBE_OPAQUE,
+ PROBE_EDI_KB9012,
+ PROBE_AT82802AB,
+ PROBE_W29EE011,
+ PROBE_EN29LV640B,
+ PROBE_SPI_AT25F,
+ PROBE_SPI_AT45DB,
+ PROBE_SPI_BIG_SPANSION,
+ PROBE_SPI_RDID,
+ PROBE_SPI_RDID4,
+ PROBE_SPI_REMS,
+ PROBE_SPI_RES1,
+ PROBE_SPI_RES2,
+ PROBE_SPI_SFDP,
+ PROBE_SPI_ST95,
+};
+
+enum write_func {
+ NO_WRITE_FUNC = 0, /* 0 indicates no write function set. */
+ WRITE_JEDEC = 1,
+ WRITE_JEDEC1,
+ WRITE_OPAQUE,
+ SPI_CHIP_WRITE1,
+ SPI_CHIP_WRITE256,
+ SPI_WRITE_AAI,
+ SPI_WRITE_AT45DB,
+ WRITE_28SF040,
+ WRITE_82802AB,
+ WRITE_EN29LV640B,
+ EDI_CHIP_WRITE,
+ TEST_WRITE_INJECTOR, /* special case must come last. */
+};
+typedef int (write_func_t)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+
+enum read_func {
+ NO_READ_FUNC = 0, /* 0 indicates no read function set. */
+ SPI_CHIP_READ = 1,
+ READ_OPAQUE,
+ READ_MEMMAPPED,
+ EDI_CHIP_READ,
+ SPI_READ_AT45DB,
+ SPI_READ_AT45DB_E8,
+ TEST_READ_INJECTOR, /* special case must come last. */
+};
+typedef int (read_func_t)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int read_flash(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+
+enum block_erase_func {
+ NO_BLOCK_ERASE_FUNC = 0, /* 0 indicates no block erase function set. */
+ SPI_BLOCK_ERASE_EMULATION = 1,
+ SPI_BLOCK_ERASE_20,
+ SPI_BLOCK_ERASE_21,
+ SPI_BLOCK_ERASE_40,
+ SPI_BLOCK_ERASE_50,
+ SPI_BLOCK_ERASE_52,
+ SPI_BLOCK_ERASE_53,
+ SPI_BLOCK_ERASE_5C,
+ SPI_BLOCK_ERASE_60,
+ SPI_BLOCK_ERASE_62,
+ SPI_BLOCK_ERASE_81,
+ SPI_BLOCK_ERASE_C4,
+ SPI_BLOCK_ERASE_C7,
+ SPI_BLOCK_ERASE_D7,
+ SPI_BLOCK_ERASE_D8,
+ SPI_BLOCK_ERASE_DB,
+ SPI_BLOCK_ERASE_DC,
+ S25FL_BLOCK_ERASE,
+ S25FS_BLOCK_ERASE_D8,
+ JEDEC_SECTOR_ERASE,
+ JEDEC_BLOCK_ERASE,
+ JEDEC_CHIP_BLOCK_ERASE,
+ OPAQUE_ERASE,
+ SPI_ERASE_AT45CS_SECTOR,
+ SPI_ERASE_AT45DB_BLOCK,
+ SPI_ERASE_AT45DB_CHIP,
+ SPI_ERASE_AT45DB_PAGE,
+ SPI_ERASE_AT45DB_SECTOR,
+ ERASE_CHIP_28SF040,
+ ERASE_SECTOR_28SF040,
+ ERASE_BLOCK_82802AB,
+ ERASE_SECTOR_49LFXXXC,
+ STM50_SECTOR_ERASE,
+ EDI_CHIP_BLOCK_ERASE,
+ TEST_ERASE_INJECTOR, /* special case must come last. */
+};
+
+enum blockprotect_func {
+ NO_BLOCKPROTECT_FUNC = 0, /* 0 indicates no unlock function set. */
+ SPI_DISABLE_BLOCKPROTECT,
+ SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD,
+ SPI_DISABLE_BLOCKPROTECT_BP1_SRWD,
+ SPI_DISABLE_BLOCKPROTECT_BP2_SRWD,
+ SPI_DISABLE_BLOCKPROTECT_BP3_SRWD,
+ SPI_DISABLE_BLOCKPROTECT_BP4_SRWD,
+ SPI_DISABLE_BLOCKPROTECT_AT45DB,
+ SPI_DISABLE_BLOCKPROTECT_AT25F,
+ SPI_DISABLE_BLOCKPROTECT_AT25FS010,
+ SPI_DISABLE_BLOCKPROTECT_AT25FS040,
+ SPI_DISABLE_BLOCKPROTECT_AT25F512A,
+ SPI_DISABLE_BLOCKPROTECT_AT25F512B,
+ SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT,
+ SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC,
+ SPI_DISABLE_BLOCKPROTECT_SST26_GLOBAL_UNPROTECT,
+ SPI_DISABLE_BLOCKPROTECT_N25Q,
+ UNLOCK_REGSPACE2_BLOCK_ERASER_0,
+ UNLOCK_REGSPACE2_BLOCK_ERASER_1,
+ UNLOCK_REGSPACE2_UNIFORM_32K,
+ UNLOCK_REGSPACE2_UNIFORM_64K,
+ UNLOCK_28F004S5,
+ UNLOCK_LH28F008BJT,
+ UNLOCK_SST_FWHUB,
+ UNPROTECT_28SF040,
+};
+
+enum printlock_func {
+ NO_PRINTLOCK_FUNC,
+ PRINTLOCK_AT49F,
+ PRINTLOCK_REGSPACE2_BLOCK_ERASER_0,
+ PRINTLOCK_REGSPACE2_BLOCK_ERASER_1,
+ PRINTLOCK_SST_FWHUB,
+ PRINTLOCK_W39F010,
+ PRINTLOCK_W39L010,
+ PRINTLOCK_W39L020,
+ PRINTLOCK_W39L040,
+ PRINTLOCK_W39V040A,
+ PRINTLOCK_W39V040B,
+ PRINTLOCK_W39V040C,
+ PRINTLOCK_W39V040FA,
+ PRINTLOCK_W39V040FB,
+ PRINTLOCK_W39V040FC,
+ PRINTLOCK_W39V080A,
+ PRINTLOCK_W39V080FA,
+ PRINTLOCK_W39V080FA_DUAL,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AMIC_A25L032,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25F,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25F4096,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512A,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512B,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS010,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS040,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT26DF081A,
+ SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP2_BPL,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD,
+ SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD,
+ SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP,
+ SPI_PRETTYPRINT_STATUS_REGISTER_EN25S_WP,
+ SPI_PRETTYPRINT_STATUS_REGISTER_N25Q,
+ SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN,
+ SPI_PRETTYPRINT_STATUS_REGISTER_SST25,
+ SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF016,
+ SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF040B,
+};
+typedef int (printlockfunc_t)(struct flashctx *flash);
+printlockfunc_t *lookup_printlock_func_ptr(struct flashctx *flash);
+
+struct flashchip {
+ const char *vendor;
+ const char *name;
+
+ enum chipbustype bustype;
+
+ /*
+ * With 32bit manufacture_id and model_id we can cover IDs up to
+ * (including) the 4th bank of JEDEC JEP106W Standard Manufacturer's
+ * Identification code.
+ */
+ uint32_t manufacture_id;
+ uint32_t model_id;
+
+ /* Total chip size in kilobytes */
+ unsigned int total_size;
+ /* Chip page size in bytes */
+ unsigned int page_size;
+ int feature_bits;
+
+ /* Indicate how well flashrom supports different operations of this flash chip. */
+ struct tested {
+ enum test_state probe;
+ enum test_state read;
+ enum test_state erase;
+ enum test_state write;
+ enum test_state wp;
+ } tested;
+
+ /*
+ * Group chips that have common command sets. This should ensure that
+ * no chip gets confused by a probing command for a very different class
+ * of chips.
+ */
+ enum {
+ /* SPI25 is very common. Keep it at zero so we don't have
+ to specify it for each and every chip in the database.*/
+ SPI25 = 0,
+ SPI_EDI = 1,
+ } spi_cmd_set;
+
+ enum probe_func probe;
+
+ /* Delay after "enter/exit ID mode" commands in microseconds.
+ * NB: negative values have special meanings, see TIMING_* below.
+ */
+ signed int probe_timing;
+
+ /*
+ * Erase blocks and associated erase function. Any chip erase function
+ * is stored as chip-sized virtual block together with said function.
+ * The logic for how to optimally select erase functions is in erasure_layout.c
+ */
+ struct block_eraser {
+ struct eraseblock {
+ unsigned int size; /* Eraseblock size in bytes */
+ unsigned int count; /* Number of contiguous blocks with that size */
+ } eraseblocks[NUM_ERASEREGIONS];
+ /* a block_erase function should try to erase one block of size
+ * 'blocklen' at address 'blockaddr' and return 0 on success. */
+ enum block_erase_func block_erase;
+ } block_erasers[NUM_ERASEFUNCTIONS];
+
+ enum printlock_func printlock;
+ enum blockprotect_func unlock;
+ enum write_func write;
+ enum read_func read;
+ struct voltage {
+ uint16_t min;
+ uint16_t max;
+ } voltage;
+ enum write_granularity gran;
+
+ struct reg_bit_map {
+ /* Status register protection bit (SRP) */
+ struct reg_bit_info srp;
+
+ /* Status register lock bit (SRP) */
+ struct reg_bit_info srl;
+
+ /*
+ * Note: some datasheets refer to configuration bits that
+ * function like TB/SEC/CMP bits as BP bits (e.g. BP3 for a bit
+ * that functions like TB).
+ *
+ * As a convention, any config bit that functions like a
+ * TB/SEC/CMP bit should be assigned to the respective
+ * tb/sec/cmp field in this structure, even if the datasheet
+ * uses a different name.
+ */
+
+ /* Block protection bits (BP) */
+ /* Extra element for terminator */
+ struct reg_bit_info bp[MAX_BP_BITS + 1];
+
+ /* Top/bottom protection bit (TB) */
+ struct reg_bit_info tb;
+
+ /* Sector/block protection bit (SEC) */
+ struct reg_bit_info sec;
+
+ /* Complement bit (CMP) */
+ struct reg_bit_info cmp;
+
+ /* Write Protect Selection (per sector protection when set) */
+ struct reg_bit_info wps;
+ } reg_bits;
+
+ /*
+ * Function that takes a set of WP config bits (e.g. BP, SEC, TB, etc)
+ * and determines what protection range they select.
+ */
+ enum decode_range_func decode_range;
+};
+
+typedef int (*chip_restore_fn_cb_t)(struct flashctx *flash, void *data);
+typedef int (blockprotect_func_t)(struct flashctx *flash);
+blockprotect_func_t *lookup_blockprotect_func_ptr(const struct flashchip *const chip);
+
+struct flashrom_flashctx {
+ struct flashchip *chip;
+ /* FIXME: The memory mappings should be saved in a more structured way. */
+ /* The physical_* fields store the respective addresses in the physical address space of the CPU. */
+ uintptr_t physical_memory;
+ /* The virtual_* fields store where the respective physical address is mapped into flashrom's address
+ * space. A value equivalent to (chipaddr)ERROR_PTR indicates an invalid mapping (or none at all). */
+ chipaddr virtual_memory;
+ /* Some flash devices have an additional register space; semantics are like above. */
+ uintptr_t physical_registers;
+ chipaddr virtual_registers;
+ struct registered_master *mst;
+ const struct flashrom_layout *layout;
+ struct flashrom_layout *default_layout;
+ struct {
+ bool force;
+ bool force_boardmismatch;
+ bool verify_after_write;
+ bool verify_whole_chip;
+ bool skip_unreadable_regions;
+ bool skip_unwritable_regions;
+ } flags;
+ /* We cache the state of the extended address register (highest byte
+ * of a 4BA for 3BA instructions) and the state of the 4BA mode here.
+ * If possible, we enter 4BA mode early. If that fails, we make use
+ * of the extended address register.
+ */
+ int address_high_byte;
+ bool in_4ba_mode;
+
+ int chip_restore_fn_count;
+ struct chip_restore_func_data {
+ chip_restore_fn_cb_t func;
+ void *data;
+ } chip_restore_fn[MAX_CHIP_RESTORE_FUNCTIONS];
+ /* Progress reporting */
+ flashrom_progress_callback *progress_callback;
+ struct flashrom_progress *progress_state;
+};
+
+/* Timing used in probe routines. ZERO is -2 to differentiate between an unset
+ * field and zero delay.
+ *
+ * SPI devices will always have zero delay and ignore this field.
+ */
+#define TIMING_FIXME -1
+/* this is intentionally same value as fixme */
+#define TIMING_IGNORED -1
+#define TIMING_ZERO -2
+
+extern const struct flashchip flashchips[];
+extern const unsigned int flashchips_size;
+
+/* parallel.c */
+void chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
+void chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr);
+void chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr);
+void chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len);
+uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr);
+uint16_t chip_readw(const struct flashctx *flash, const chipaddr addr);
+uint32_t chip_readl(const struct flashctx *flash, const chipaddr addr);
+void chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len);
+
+/* print.c */
+int print_supported(void);
+void print_supported_wiki(void);
+
+/* helpers.c */
+uint32_t address_to_bits(uint32_t addr);
+unsigned int bitcount(unsigned long a);
+#undef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#undef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+int max(int a, int b);
+int min(int a, int b);
+char *strcat_realloc(char *dest, const char *src);
+void tolower_string(char *str);
+uint8_t reverse_byte(uint8_t x);
+void reverse_bytes(uint8_t *dst, const uint8_t *src, size_t length);
+#ifdef __MINGW32__
+char* strtok_r(char *str, const char *delim, char **nextp);
+char *strndup(const char *str, size_t size);
+#endif
+#if defined(__DJGPP__) || (!defined(__LIBPAYLOAD__) && !defined(HAVE_STRNLEN))
+size_t strnlen(const char *str, size_t n);
+#endif
+
+/* flashrom.c */
+extern const char flashrom_version[];
+char *flashbuses_to_text(enum chipbustype bustype);
+int map_flash(struct flashctx *flash);
+void unmap_flash(struct flashctx *flash);
+int read_memmapped(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int erase_flash(struct flashctx *flash);
+int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force, const char *const chip_to_probe);
+int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int start, unsigned int len);
+void emergency_help_message(void);
+void print_version(void);
+void print_buildinfo(void);
+void print_banner(void);
+void list_programmers_linebreak(int startcol, int cols, int paren);
+int selfcheck(void);
+int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename);
+int write_buf_to_file(const unsigned char *buf, unsigned long size, const char *filename);
+int prepare_flash_access(struct flashctx *, bool read_it, bool write_it, bool erase_it, bool verify_it);
+void finalize_flash_access(struct flashctx *);
+int register_chip_restore(chip_restore_fn_cb_t func, struct flashctx *flash, void *data);
+int check_block_eraser(const struct flashctx *flash, int k, int log);
+unsigned int count_usable_erasers(const struct flashctx *flash);
+int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran, const uint8_t erased_value);
+erasefunc_t *lookup_erase_func_ptr(const struct block_eraser *const eraser);
+int check_erased_range(struct flashctx *flash, unsigned int start, unsigned int len);
+unsigned int get_next_write(const uint8_t *have, const uint8_t *want, unsigned int len, unsigned int *first_start, enum write_granularity gran);
+int write_flash(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+
+/* Something happened that shouldn't happen, but we can go on. */
+#define ERROR_FLASHROM_NONFATAL 0x100
+
+/* Something happened that shouldn't happen, we'll abort. */
+#define ERROR_FLASHROM_FATAL -0xee
+#define ERROR_FLASHROM_BUG -200
+/* We reached one of the hardcoded limits of flashrom. This can be fixed by
+ * increasing the limit of a compile-time allocation or by switching to dynamic
+ * allocation.
+ * Note: If this warning is triggered, check first for runaway registrations.
+ */
+#define ERROR_FLASHROM_LIMIT -201
+
+/* cli_common.c */
+void print_chip_support_status(const struct flashchip *chip);
+
+/* cli_output.c */
+extern enum flashrom_log_level verbose_screen;
+extern enum flashrom_log_level verbose_logfile;
+int open_logfile(const char * const filename);
+int close_logfile(void);
+void start_logging(void);
+int flashrom_print_cb(enum flashrom_log_level level, const char *fmt, va_list ap);
+void flashrom_progress_cb(struct flashrom_flashctx *flashctx);
+/* Let gcc and clang check for correct printf-style format strings. */
+int print(enum flashrom_log_level level, const char *fmt, ...)
+#ifdef __MINGW32__
+# ifndef __MINGW_PRINTF_FORMAT
+# define __MINGW_PRINTF_FORMAT gnu_printf
+# endif
+__attribute__((format(__MINGW_PRINTF_FORMAT, 2, 3)));
+#else
+__attribute__((format(printf, 2, 3)));
+#endif
+#define msg_gerr(...) print(FLASHROM_MSG_ERROR, __VA_ARGS__) /* general errors */
+#define msg_perr(...) print(FLASHROM_MSG_ERROR, __VA_ARGS__) /* programmer errors */
+#define msg_cerr(...) print(FLASHROM_MSG_ERROR, __VA_ARGS__) /* chip errors */
+#define msg_gwarn(...) print(FLASHROM_MSG_WARN, __VA_ARGS__) /* general warnings */
+#define msg_pwarn(...) print(FLASHROM_MSG_WARN, __VA_ARGS__) /* programmer warnings */
+#define msg_cwarn(...) print(FLASHROM_MSG_WARN, __VA_ARGS__) /* chip warnings */
+#define msg_ginfo(...) print(FLASHROM_MSG_INFO, __VA_ARGS__) /* general info */
+#define msg_pinfo(...) print(FLASHROM_MSG_INFO, __VA_ARGS__) /* programmer info */
+#define msg_cinfo(...) print(FLASHROM_MSG_INFO, __VA_ARGS__) /* chip info */
+#define msg_gdbg(...) print(FLASHROM_MSG_DEBUG, __VA_ARGS__) /* general debug */
+#define msg_pdbg(...) print(FLASHROM_MSG_DEBUG, __VA_ARGS__) /* programmer debug */
+#define msg_cdbg(...) print(FLASHROM_MSG_DEBUG, __VA_ARGS__) /* chip debug */
+#define msg_gdbg2(...) print(FLASHROM_MSG_DEBUG2, __VA_ARGS__) /* general debug2 */
+#define msg_pdbg2(...) print(FLASHROM_MSG_DEBUG2, __VA_ARGS__) /* programmer debug2 */
+#define msg_cdbg2(...) print(FLASHROM_MSG_DEBUG2, __VA_ARGS__) /* chip debug2 */
+#define msg_gspew(...) print(FLASHROM_MSG_SPEW, __VA_ARGS__) /* general debug spew */
+#define msg_pspew(...) print(FLASHROM_MSG_SPEW, __VA_ARGS__) /* programmer debug spew */
+#define msg_cspew(...) print(FLASHROM_MSG_SPEW, __VA_ARGS__) /* chip debug spew */
+void update_progress(struct flashctx *flash, enum flashrom_progress_stage stage, size_t current, size_t total);
+
+/* spi.c */
+struct spi_command {
+ unsigned int writecnt;
+ unsigned int readcnt;
+ const unsigned char *writearr;
+ unsigned char *readarr;
+};
+#define NULL_SPI_CMD { 0, 0, NULL, NULL, }
+int spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
+int spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds);
+
+enum chipbustype get_buses_supported(void);
+#endif /* !__FLASH_H__ */
diff --git a/include/flashchips.h b/include/flashchips.h
new file mode 100644
index 000000000..962e65e4d
--- /dev/null
+++ b/include/flashchips.h
@@ -0,0 +1,1055 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2000 Silicon Integrated System Corporation
+ * Copyright (C) 2000 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2005-2007 coresystems GmbH <stepan@coresystems.de>
+ * Copyright (C) 2006-2009 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __FLASHCHIPS_H__
+#define __FLASHCHIPS_H__ 1
+
+/*
+ * Please keep this list sorted alphabetically by manufacturer. The first
+ * entry of each section should be the manufacturer ID, followed by the
+ * list of devices from that manufacturer (sorted by device ID).
+ *
+ * Most LPC/FWH parts (parallel flash) have 8-bit device IDs if there is no
+ * continuation code.
+ * SPI parts have at least 16-bit device IDs if they support RDID.
+ */
+
+#define GENERIC_MANUF_ID 0xFFFF /* Check if there is a vendor ID */
+#define GENERIC_DEVICE_ID 0xFFFF /* Only match the vendor ID */
+#define SFDP_DEVICE_ID 0xFFFE
+#define PROGMANUF_ID 0xFFFE /* dummy ID for opaque chips behind a programmer */
+#define PROGDEV_ID 0x01 /* dummy ID for opaque chips behind a programmer */
+
+#define ALLIANCE_ID 0x52 /* Alliance Semiconductor */
+#define ALLIANCE_AS29F002B 0x34
+#define ALLIANCE_AS29F002T 0xB0
+#define ALLIANCE_AS29F010 0x04
+#define ALLIANCE_AS29F040 0xA4
+#define ALLIANCE_AS29F200B 0x57
+#define ALLIANCE_AS29F200T 0x51
+#define ALLIANCE_AS29LV160B 0x49
+#define ALLIANCE_AS29LV160T 0xCA
+#define ALLIANCE_AS29LV400B 0xBA
+#define ALLIANCE_AS29LV400T 0xB9
+#define ALLIANCE_AS29LV800B 0x5B
+#define ALLIANCE_AS29LV800T 0xDA
+
+#define AMD_ID 0x01 /* AMD */
+#define AMD_AM29DL400BT 0x0C
+#define AMD_AM29DL400BB 0x0F
+#define AMD_AM29DL800BT 0x4A
+#define AMD_AM29DL800BB 0xCB
+#define AMD_AM29F002BB 0x34 /* Same as Am29F002NBB */
+#define AMD_AM29F002BT 0xB0 /* Same as Am29F002NBT */
+#define AMD_AM29F004BB 0x7B
+#define AMD_AM29F004BT 0x77
+#define AMD_AM29F016D 0xAD
+#define AMD_AM29F010 0x20 /* Same as Am29F010A and Am29F010B */
+#define AMD_AM29F040 0xA4 /* Same as AM29F040B */
+#define AMD_AM29F080 0xD5 /* Same as Am29F080B */
+#define AMD_AM29F200BB 0x57
+#define AMD_AM29F200BT 0x51
+#define AMD_AM29F400BB 0xAB
+#define AMD_AM29F400BT 0x23
+#define AMD_AM29F800BB 0x58
+#define AMD_AM29F800BT 0xD6
+#define AMD_AM29LV001BB 0x6D
+#define AMD_AM29LV001BT 0xED
+#define AMD_AM29LV010B 0x6E /* 1Mb, uniform */
+#define AMD_AM29LV002BB 0xC2
+#define AMD_AM29LV002BT 0x40
+#define AMD_AM29LV004BB 0xB6
+#define AMD_AM29LV004BT 0xB5
+#define AMD_AM29LV008BB 0x37
+#define AMD_AM29LV008BT 0x3E
+#define AMD_AM29LV040B 0x4F
+#define AMD_AM29LV080B 0x38 /* Same as Am29LV081B */
+#define AMD_AM29LV200BB 0xBF
+#define AMD_AM29LV200BT 0x3B
+#define AMD_AM29LV800BB 0x5B /* Same as Am29LV800DB */
+#define AMD_AM29LV400BT 0xB9
+#define AMD_AM29LV400BB 0xBA
+#define AMD_AM29LV800BT 0xDA /* Same as Am29LV800DT */
+
+#define AMIC_ID 0x7F37 /* AMIC */
+#define AMIC_ID_NOPREFIX 0x37 /* AMIC */
+#define AMIC_A25L05PT 0x2020
+#define AMIC_A25L05PU 0x2010
+#define AMIC_A25L10PT 0x2021
+#define AMIC_A25L10PU 0x2011
+#define AMIC_A25L20PT 0x2022
+#define AMIC_A25L20PU 0x2012
+#define AMIC_A25L40PT 0x2013 /* Datasheet says T and U have
+ same device ID. Confirmed by
+ hardware testing. */
+#define AMIC_A25L40PU 0x2013
+#define AMIC_A25L80P 0x2014 /* Seems that no A25L80PT exists */
+#define AMIC_A25L16PT 0x2025
+#define AMIC_A25L16PU 0x2015
+#define AMIC_A25L512 0x3010
+#define AMIC_A25L010 0x3011
+#define AMIC_A25L020 0x3012
+#define AMIC_A25L040 0x3013
+#define AMIC_A25L080 0x3014
+#define AMIC_A25L016 0x3015
+#define AMIC_A25L032 0x3016
+#define AMIC_A25LQ16 0x4015
+#define AMIC_A25LQ032 0x4016 /* Same as A25LQ32A, but the latter supports SFDP */
+#define AMIC_A25LQ64 0x4017
+#define AMIC_A29002B 0x0d
+#define AMIC_A29002T 0x8C /* Same as A290021T */
+#define AMIC_A29040B 0x86
+#define AMIC_A29400T 0xB0 /* Same as 294001T */
+#define AMIC_A29400U 0x31 /* Same as A294001U */
+#define AMIC_A29800T 0x0E
+#define AMIC_A29800U 0x8F
+#define AMIC_A29L004T 0x34 /* Same as A29L400T */
+#define AMIC_A29L004U 0xB5 /* Same as A29L400U */
+#define AMIC_A29L008T 0x1A /* Same as A29L800T */
+#define AMIC_A29L008U 0x9B /* Same as A29L800U */
+#define AMIC_A29L040 0x92
+#define AMIC_A49LF040A 0x9d
+
+#define ATMEL_ID 0x1F /* Atmel (now used by Adesto) */
+#define ATMEL_AT25DF011 0x4200
+#define ATMEL_AT25DF021 0x4300
+#define ATMEL_AT25DF021A 0x4301
+#define ATMEL_AT25DF041A 0x4401
+#define ATMEL_AT25DF081 0x4502 /* EDI 0x00. AT25DL081 has same ID + EDI 0x0100 */
+#define ATMEL_AT25DF081A 0x4501 /* Yes, 81A has a lower number than 81 */
+#define ATMEL_AT25DF161 0x4602
+#define ATMEL_AT25DF321 0x4700 /* Same as 26DF321 */
+#define ATMEL_AT25DF321A 0x4701
+#define ATMEL_AT25DF641 0x4800
+#define ATMEL_AT25DL161 0x4603 /* EDI 0x0100 */
+#define ATMEL_AT25DQ161 0x8600 /* EDI 0x0100 */
+#define ATMEL_AT25DQ321 0x8700 /* EDI 0x0100 */
+#define ATMEL_AT25F512 0x60 /* Needs AT25F_RDID. ID from PCN and actual HW. Seems to be a relabeled AT25F1024. */
+#define ATMEL_AT25F512A 0x65 /* Needs AT25F_RDID */
+#define ATMEL_AT25F512B 0x6500
+#define ATMEL_AT25F1024 0x60 /* Needs AT25F_RDID */
+#define ATMEL_AT25F2048 0x63 /* Needs AT25F_RDID */
+#define ATMEL_AT25F4096 0x64 /* Needs AT25F_RDID */
+#define ATMEL_AT25FS010 0x6601
+#define ATMEL_AT25FS040 0x6604
+#define ATMEL_AT25SF041 0x8401
+#define ATMEL_AT25SF081 0x8501
+#define ATMEL_AT25SF161 0x8601
+#define ATMEL_AT25SF321 0x8701
+#define ATMEL_AT25SL128A 0x4218
+#define ATMEL_AT25SF128A 0x8901 /* Adesto AT25SF128A */
+#define ATMEL_AT26DF041 0x4400
+#define ATMEL_AT26DF081 0x4500 /* guessed, no datasheet available */
+#define ATMEL_AT26DF081A 0x4501
+#define ATMEL_AT26DF161 0x4600
+#define ATMEL_AT26DF161A 0x4601
+#define ATMEL_AT26F004 0x0400
+#define ATMEL_AT29LV512 0x3D
+#define ATMEL_AT29LV010A 0x35 /* Same as AT29BV010A, the latter works down to 2.7V */
+#define ATMEL_AT29LV020 0xBA
+#define ATMEL_AT29BV040A 0xC4
+#define ATMEL_AT29C040A 0xA4
+#define ATMEL_AT29C010A 0xD5
+#define ATMEL_AT29C020 0xDA
+#define ATMEL_AT29C512 0x5D
+#define ATMEL_AT45BR3214B /* No ID available */
+#define ATMEL_AT45CS1282 0x2920
+#define ATMEL_AT45D011 /* No ID available */
+#define ATMEL_AT45D021A /* No ID available */
+#define ATMEL_AT45D041A /* No ID available */
+#define ATMEL_AT45D081A /* No ID available */
+#define ATMEL_AT45D161 /* No ID available */
+#define ATMEL_AT45DB011 /* No ID (opcode) available for AT45DB011, AT45DB011B */
+#define ATMEL_AT45DB011D 0x2200
+#define ATMEL_AT45DB021 /* No ID (opcode) available for AT45DB021, AT45DB021A, AT45DB021B */
+#define ATMEL_AT45DB021D 0x2300
+#define ATMEL_AT45DB021E /* same as above but with EDI 0x0100 */
+#define ATMEL_AT45DB041 /* No ID (opcode) available for AT45DB041, AT45DB041A, AT45DB041B */
+#define ATMEL_AT45DB041D 0x2400
+#define ATMEL_AT45DB041E /* same as above but with EDI 0x0100 */
+#define ATMEL_AT45DB081 /* No ID (opcode) available for AT45DB081, AT45DB081A, AT45DB081B */
+#define ATMEL_AT45DB081D 0x2500
+#define ATMEL_AT45DB081E /* same as above but with EDI 0x0100 */
+#define ATMEL_AT45DB161 /* No ID (opcode) available for AT45DB161, AT45DB161B */
+#define ATMEL_AT45DB161D 0x2600
+#define ATMEL_AT45DB161E /* same as above but with EDI 0x0100 */
+#define ATMEL_AT45DB321 /* No ID (opcode) available for AT45DB321, AT45DB321B */
+#define ATMEL_AT45DB321C 0x2700
+#define ATMEL_AT45DB321E /* same as above but with EDI 0x0100 */
+#define ATMEL_AT45DB321D 0x2701 /* Buggy data sheet */
+#define ATMEL_AT45DB642 /* No ID (opcode) available for AT45DB642 */
+#define ATMEL_AT45DB642D 0x2800
+#define ATMEL_AT49BV512 0x03 /* Same as AT49F512 */
+#define ATMEL_AT49F001N 0x05 /* Same as AT49F001 */
+#define ATMEL_AT49F001NT 0x04 /* Same as AT49F001T */
+#define ATMEL_AT49F002N 0x07 /* for AT49F002(N) */
+#define ATMEL_AT49LH002 0xE9
+#define ATMEL_AT49LH00B4 0xED
+#define ATMEL_AT49LH004 0xEE
+#define ATMEL_AT49F002NT 0x08 /* for AT49F002(N)T */
+#define ATMEL_AT49F010 0x17 /* Same as AT49HF010 (some erroneous datasheets say 0x87), AT49BV010, AT49HBV010, AT49HLV010 */
+#define ATMEL_AT49F020 0x0B
+#define ATMEL_AT49F040 0x13
+#define ATMEL_AT49F080 0x23
+#define ATMEL_AT49F080T 0x27
+
+/* Boya/BoHong Microelectronics Inc. */
+#define BOYA_BOHONG_ID 0x68
+#define BOYA_BOHONG_B__25D80A 0x4014
+#define BOYA_BOHONG_B_25D16A 0x4015
+#define BOYA_BOHONG_B_25Q128AS 0x4018
+
+/* Bright Microelectronics has the same manufacturer ID as Hyundai... */
+#define BRIGHT_ID 0xAD /* Bright Microelectronics */
+#define BRIGHT_BM29F040 0x40
+#define BRIGHT_BM29F400B 0xAB
+#define BRIGHT_BM29F400T 0xAD
+
+#define CATALYST_ID 0x31 /* Catalyst */
+#define CATALYST_CAT28F512 0xB8
+
+#define ESMT_ID 0x8C /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */
+#define ESMT_F25L008A 0x2014
+#define ESMT_F25L32PA 0x2016
+#define ESMT_F25D08QA 0x2534
+#define ESMT_F25L16QA2S 0x4015
+#define ESMT_F25L32QA 0x4016
+#define ESMT_F25L32QA2S 0x4116
+#define ESMT_F25L64QA 0x4117
+#define ESMT_F25L128QA 0x4118
+#define ESMT_F49B002UA 0x00
+
+/*
+ * EN25 chips are SPI, first byte of device ID is memory type,
+ * second byte of device ID is log(bitsize)-9.
+ * Vendor and device ID of EN29 series are both prefixed with 0x7F, which
+ * is the continuation code for IDs in bank 2.
+ * Vendor ID of EN25 series is NOT prefixed with 0x7F, this results in
+ * a collision with Mitsubishi. Mitsubishi once manufactured flash chips.
+ * Let's hope they are not manufacturing SPI flash chips as well.
+ */
+#define EON_ID 0x7F1C /* EON Silicon Devices */
+#define EON_ID_NOPREFIX 0x1C /* EON, missing 0x7F prefix */
+#define EON_EN25B05 0x2010 /* Same as EN25P05, can be distinguished by RES/REMS: */
+#define EON_EN25P05 0x05
+#define EON_EN25B05T 0x25
+#define EON_EN25B05B 0x95
+#define EON_EN25B10 0x2011 /* Same as EN25P10, can be distinguished by RES/REMS: */
+#define EON_EN25P10 0x10
+#define EON_EN25B10T 0x40
+#define EON_EN25B10B 0x30
+#define EON_EN25B20 0x2012 /* Same as EN25P20, can be distinguished by RES/REMS: */
+#define EON_EN25P20 0x11
+#define EON_EN25B20T 0x41
+#define EON_EN25B20B 0x31
+#define EON_EN25B40 0x2013 /* Same as EN25P40, can be distinguished by RES/REMS: */
+#define EON_EN25P40 0x12
+#define EON_EN25B40T 0x42
+#define EON_EN25B40B 0x32
+#define EON_EN25B80 0x2014 /* Same as EN25P80, can be distinguished by RES/REMS: */
+#define EON_EN25P80 0x13
+#define EON_EN25B80T 0x43
+#define EON_EN25B80B 0x33
+#define EON_EN25B16 0x2015 /* Same as EN25P16, can be distinguished by RES/REMS: */
+#define EON_EN25P16 0x14
+#define EON_EN25B16T 0x44
+#define EON_EN25B16B 0x34
+#define EON_EN25B32 0x2016 /* Same as EN25P32, can be distinguished by RES/REMS: */
+#define EON_EN25P32 0x15
+#define EON_EN25B32T 0x45
+#define EON_EN25B32B 0x35
+#define EON_EN25B64 0x2017 /* Same as EN25P64, can be distinguished by RES/REMS: */
+#define EON_EN25P64 0x16
+#define EON_EN25B64T 0x46
+#define EON_EN25B64B 0x36
+#define EON_EN25F05 0x3110
+#define EON_EN25F10 0x3111
+#define EON_EN25F20 0x3112
+#define EON_EN25F40 0x3113
+#define EON_EN25F80 0x3114
+#define EON_EN25F16 0x3115
+#define EON_EN25F32 0x3116
+#define EON_EN25F64 0x3117
+#define EON_EN25Q40 0x3013
+#define EON_EN25Q80 0x3014
+#define EON_EN25Q16 0x3015 /* Same as EN25D16 */
+#define EON_EN25Q32 0x3016 /* Same as EN25Q32A and EN25Q32B */
+#define EON_EN25Q64 0x3017
+#define EON_EN25Q128 0x3018
+#define EON_EN25QH16 0x7015
+#define EON_EN25QH32 0x7016
+#define EON_EN25QH64 0x7017
+#define EON_EN25QH128 0x7018
+#define EON_EN25QH256 0x7019
+#define EON_EN25S10 0x3811
+#define EON_EN25S20 0x3812
+#define EON_EN25S40 0x3813
+#define EON_EN25S80 0x3814
+#define EON_EN25S16 0x3815
+#define EON_EN25S32 0x3816
+#define EON_EN25S64 0x3817
+#define EON_EN25T80 0x5114
+#define EON_EN25T16 0x5115
+#define EON_EN29F512 0x7F21
+#define EON_EN29F010 0x20
+#define EON_EN29F040A 0x7F04
+#define EON_EN29LV010 0x7F6E
+#define EON_EN29LV040 0x4F /* Same as EN29LV040A */
+#define EON_EN29LV640B 0xCB
+#define EON_EN29LV640T 0xC9
+#define EON_EN29LV640U 0x7E
+#define EON_EN29F002T 0x7F92 /* Same as EN29F002A */
+#define EON_EN29F002B 0x7F97 /* Same as EN29F002AN */
+#define EON_EN29GL064HL 0x7E0C01 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define EON_EN29GL064T 0x7E1001 /* Same ID as EN29GL064AT */
+#define EON_EN29GL064B 0x7E1000 /* Same ID as EN29GL064AB */
+#define EON_EN29GL128HL 0x7F2101 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define EON_EN29GL256HL 0x7F2201 /* Uniform Sectors, WP protects Top OR Bottom sector */
+
+#define EXCEL_ID 0x7F7F7F7F4A /* Excel Semiconductor Inc. (ESI) resides in bank 5 */
+#define EXCEL_ID_NOPREFIX 0x4A /* ESI, missing 0x7F prefix */
+#define EXCEL_ES25P40 0x2013
+#define EXCEL_ES25P80 0x2014
+#define EXCEL_ES25P16 0x2015
+
+#define FIDELIX_ID 0xF8 /* Fidelix */
+#define FIDELIX_FM25M16 0x4215
+#define FIDELIX_FM25M32 0x4216
+#define FIDELIX_FM25M64 0x4217
+#define FIDELIX_FM25Q08 0x3214
+#define FIDELIX_FM25Q16 0x3215 /* Same as FM25S16 (which is apparently single I/O only) */
+#define FIDELIX_FM25Q32 0x3216
+#define FIDELIX_FM25Q64 0x3217
+
+#define FUDAN_ID 0x7F7F7F7F7F7F7FA1 /* Shanghai Fudan Microelectronics resides in bank 8 */
+#define FUDAN_ID_NOPREFIX 0xA1 /* Fudan, missing 0x7F prefix */
+#define FUDAN_FM25F005 0x3110
+#define FUDAN_FM25F01 0x3111
+#define FUDAN_FM25F02 0x3112 /* Same as FM25F02A */
+#define FUDAN_FM25F04 0x3113 /* Same as FM25F04A */
+#define FUDAN_FM25Q08 0x4014
+#define FUDAN_FM25Q16 0x4015
+#define FUDAN_FM25Q32 0x4016
+
+#define FUJITSU_ID 0x04 /* Fujitsu */
+#define FUJITSU_MBM29DL400BC 0x0F
+#define FUJITSU_MBM29DL400TC 0x0C
+#define FUJITSU_MBM29DL800BA 0xCB
+#define FUJITSU_MBM29DL800TA 0x4A
+#define FUJITSU_MBM29F002BC 0x34
+#define FUJITSU_MBM29F002TC 0xB0
+#define FUJITSU_MBM29F004BC 0x7B
+#define FUJITSU_MBM29F004TC 0x77
+#define FUJITSU_MBM29F040C 0xA4
+#define FUJITSU_MBM29F080A 0xD5
+#define FUJITSU_MBM29F200BC 0x57
+#define FUJITSU_MBM29F200TC 0x51
+#define FUJITSU_MBM29F400BC 0xAB
+#define FUJITSU_MBM29F400TC 0x23
+#define FUJITSU_MBM29F800BA 0x58
+#define FUJITSU_MBM29F800TA 0xD6
+#define FUJITSU_MBM29LV002BC 0xC2
+#define FUJITSU_MBM29LV002TC 0x40
+#define FUJITSU_MBM29LV004BC 0xB6
+#define FUJITSU_MBM29LV004TC 0xB5
+#define FUJITSU_MBM29LV008BA 0x37
+#define FUJITSU_MBM29LV008TA 0x3E
+#define FUJITSU_MBM29LV080A 0x38
+#define FUJITSU_MBM29LV200BC 0xBF
+#define FUJITSU_MBM29LV200TC 0x3B
+#define FUJITSU_MBM29LV400BC 0xBA
+#define FUJITSU_MBM29LV400TC 0xB9
+#define FUJITSU_MBM29LV800BA 0x5B /* Same as MBM29LV800BE */
+#define FUJITSU_MBM29LV800TA 0xDA /* Same as MBM29LV800TE */
+#define FUJITSU_MBM29LV160BE 0x49 /* 16 b mode 0x2249 */
+#define FUJITSU_MBM29LV160TE 0xC4 /* 16 b mode 0x22C4 */
+
+#define GIGADEVICE_ID 0xC8 /* GigaDevice */
+#define GIGADEVICE_GD25T80 0x3114
+#define GIGADEVICE_GD25Q512 0x4010
+#define GIGADEVICE_GD25Q10 0x4011
+#define GIGADEVICE_GD25Q20 0x4012 /* Same as GD25QB */
+#define GIGADEVICE_GD25Q40 0x4013 /* Same as GD25QB */
+#define GIGADEVICE_GD25Q80 0x4014 /* Same as GD25Q80B (which has OTP) */
+#define GIGADEVICE_GD25Q16 0x4015 /* Same as GD25Q16B (which has OTP) */
+#define GIGADEVICE_GD25Q32 0x4016 /* Same as GD25Q32B */
+#define GIGADEVICE_GD25Q64 0x4017 /* Same as GD25Q64B */
+#define GIGADEVICE_GD25Q128 0x4018 /* GD25Q128B and GD25Q128C only, can be distinguished by SFDP */
+#define GIGADEVICE_GD25Q256D 0x4019
+#define GIGADEVICE_GD25VQ21B 0x4212
+#define GIGADEVICE_GD25VQ41B 0x4213 /* Same as GD25VQ40C, can be distinguished by SFDP */
+#define GIGADEVICE_GD25VQ80C 0x4214
+#define GIGADEVICE_GD25VQ16C 0x4215
+#define GIGADEVICE_GD25LQ40 0x6013
+#define GIGADEVICE_GD25LQ80 0x6014
+#define GIGADEVICE_GD25LQ16 0x6015
+#define GIGADEVICE_GD25LQ32 0x6016
+#define GIGADEVICE_GD25LQ64 0x6017 /* Same as GD25LQ64B (which is faster) */
+#define GIGADEVICE_GD25LQ128CD 0x6018
+#define GIGADEVICE_GD25WQ80E 0x6514
+#define GIGADEVICE_GD29GL064CAB 0x7E0601
+
+#define HYUNDAI_ID 0xAD /* Hyundai */
+#define HYUNDAI_HY29F400T 0x23 /* Same as HY29F400AT */
+#define HYUNDAI_HY29F800B 0x58 /* Same as HY29F800AB */
+#define HYUNDAI_HY29LV800B 0x5B
+#define HYUNDAI_HY29F040A 0xA4
+#define HYUNDAI_HY29F400B 0xAB /* Same as HY29F400AB */
+#define HYUNDAI_HY29F002B 0x34
+#define HYUNDAI_HY29F002T 0xB0
+#define HYUNDAI_HY29LV400T 0xB9
+#define HYUNDAI_HY29LV400B 0xBA
+#define HYUNDAI_HY29F080 0xD5
+#define HYUNDAI_HY29F800T 0xD6 /* Same as HY29F800AT */
+#define HYUNDAI_HY29LV800T 0xDA
+
+#define IMT_ID 0x7F1F /* Integrated Memory Technologies */
+#define IMT_IM29F004B 0xAE
+#define IMT_IM29F004T 0xAF
+
+#define INTEL_ID 0x89 /* Intel */
+#define INTEL_28F320J5 0x14
+#define INTEL_28F640J5 0x15
+#define INTEL_28F320J3 0x16
+#define INTEL_28F640J3 0x17
+#define INTEL_28F128J3 0x18
+#define INTEL_28F256J3 0x1D
+#define INTEL_28F400T 0x70 /* 28F400BV/BX/CE/CV-T */
+#define INTEL_28F400B 0x71 /* 28F400BV/BX/CE/CV-B */
+#define INTEL_28F200T 0x74 /* 28F200BL/BV/BX/CV-T */
+#define INTEL_28F200B 0x75 /* 28F200BL/BV/BX/CV-B */
+#define INTEL_28F004T 0x78 /* 28F004B5/BE/BV/BX-T */
+#define INTEL_28F004B 0x79 /* 28F004B5/BE/BV/BX-B */
+#define INTEL_28F002T 0x7C /* 28F002BC/BL/BV/BX-T */
+#define INTEL_28F002B 0x7D /* 28F002BL/BV/BX-B */
+#define INTEL_28F001T 0x94 /* 28F001BN/BX-T */
+#define INTEL_28F001B 0x95 /* 28F001BN/BX-B */
+#define INTEL_28F008T 0x98 /* 28F008BE/BV-T */
+#define INTEL_28F008B 0x99 /* 28F008BE/BV-B */
+#define INTEL_28F800T 0x9C /* 28F800B5/BV/CE/CV-T */
+#define INTEL_28F800B 0x9D /* 28F800B5/BV/CE/CV-B */
+#define INTEL_28F016SV 0xA0 /* 28F016SA/SV */
+#define INTEL_28F008SA 0xA2
+#define INTEL_28F008S3 0xA6 /* 28F008S3/S5/SC */
+#define INTEL_28F004S3 0xA7 /* 28F008S3/S5/SC */
+#define INTEL_28F016XS 0xA8
+#define INTEL_28F016S3 0xAA /* 28F016S3/S5/SC */
+#define INTEL_82802AC 0xAC
+#define INTEL_82802AB 0xAD
+#define INTEL_28F010 0xB4
+#define INTEL_28F512 0xB8
+#define INTEL_28F256A 0xB9
+#define INTEL_28F020 0xBD
+#define INTEL_28F016B3T 0xD0 /* 28F016B3-T */
+#define INTEL_28F016B3B 0xD1 /* 28F016B3-B */
+#define INTEL_28F008B3T 0xD2 /* 28F008B3-T */
+#define INTEL_28F008B3B 0xD3 /* 28F008B3-B */
+#define INTEL_28F004B3T 0xD4 /* 28F004B3-T */
+#define INTEL_28F004B3B 0xD5 /* 28F004B3-B */
+#define INTEL_25F160S33B8 0x8911 /* Same as 25F016S33B8 */
+#define INTEL_25F320S33B8 0x8912
+#define INTEL_25F640S33B8 0x8913
+#define INTEL_25F160S33T8 0x8915 /* Same as 25F016S33T8 */
+#define INTEL_25F320S33T8 0x8916
+#define INTEL_25F640S33T8 0x8917
+
+#define SHARP_LH28F008SA 0xA2 /* Sharp chip, Intel Vendor ID */
+#define SHARP_LH28F008SC 0xA6 /* Sharp chip, Intel Vendor ID */
+
+#define ISSI_ID 0xD5 /* ISSI Integrated Silicon Solutions, see also PMC. */
+#define ISSI_ID_SPI 0x9D /* ISSI ID used for SPI flash, see also PMC_ID_NOPREFIX */
+#define ISSI_IS25LP016 0x6015
+#define ISSI_IS25LP064 0x6017
+#define ISSI_IS25LP128 0x6018
+#define ISSI_IS25LP256 0x6019
+#define ISSI_IS25LQ016 0x1445
+#define ISSI_IS25WP016 0x7015
+#define ISSI_IS25WP020 0x7012
+#define ISSI_IS25WP032 0x7016
+#define ISSI_IS25WP040 0x7013
+#define ISSI_IS25WP064 0x7017
+#define ISSI_IS25WP080 0x7014
+#define ISSI_IS25WP128 0x7018
+#define ISSI_IS25WP256 0x7019
+#define ISSI_IS25WQ040 0x1253
+#define ISSI_PMC_IS29GL032B 0xF9
+#define ISSI_PMC_IS29GL032T 0xF6
+#define ISSI_PMC_IS29GL064B 0x7E1000
+#define ISSI_PMC_IS29GL064T 0x7E1001
+#define ISSI_PMC_IS29GL064HL 0x7E0C01
+#define ISSI_PMC_IS29GL128HL 0x7E2101
+#define ISSI_PMC_IS29GL256HL 0x7E2201
+
+#define MACRONIX_ID 0xC2 /* Macronix (MX) */
+/* Mask ROMs */
+#define MACRONIX_MX23L1654 0x0515
+#define MACRONIX_MX23L3254 0x0516
+#define MACRONIX_MX23L6454 0x0517
+#define MACRONIX_MX23L12854 0x0518
+/* MX25 chips are SPI, first byte of device ID is memory type,
+ * second byte of device ID is log(bitsize)-9.
+ * Generalplus SPI chips seem to be compatible with Macronix
+ * and use the same set of IDs. */
+#define MACRONIX_MX25L512 0x2010 /* Same as MX25L512E, MX25V512, MX25V512C */
+#define MACRONIX_MX25L5121E 0x2210
+#define MACRONIX_MX25L1005 0x2011 /* Same as MX25L1005C, MX25L1006E */
+#define MACRONIX_MX25L2005 0x2012 /* Same as MX25L2005C, MX25L2006E */
+#define MACRONIX_MX25L4005 0x2013 /* Same as MX25L4005A, MX25L4005C, MX25L4006E */
+#define MACRONIX_MX25L8005 0x2014 /* Same as MX25V8005, MX25L8006E, MX25L8008E, FIXME: MX25L8073E (4k 0x20) */
+#define MACRONIX_MX25L1605 0x2015 /* MX25L1605 (64k 0x20); MX25V16066 (4k 0x20, 32k 0x52, 64k 0xD8); MX25L1605A/MX25L1606E/MX25L1608E (4k 0x20, 64k 0x52); MX25L1605D/MX25L1608D/MX25L1673E (4k 0x20) */
+#define MACRONIX_MX25L3205 0x2016 /* MX25L3205, MX25L3205A (64k 0x20); MX25L3205D/MX25L3208D (4k 0x20); MX25L3206E/MX25L3208E (4k 0x20, 64k 0x52); MX25L3233F/MX25L3273E (4k 0x20, 32k 0x52) */
+#define MACRONIX_MX25L6405 0x2017 /* MX25L6405, MX25L6405D (64k 0x20); MX25L6406E/MX25L6408E (4k 0x20); MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E (4k 0x20, 32k 0x52) */
+#define MACRONIX_MX25L12805D 0x2018 /* MX25L12805D (no 32k); MX25L12865E, MX25L12835F, MX25L12845E, MX25L12873F, MX25L12833F (32k 0x52) */
+#define MACRONIX_MX25L25635F 0x2019 /* Same as MX25L25639F, but the latter seems to not support REMS */
+#define MACRONIX_MX25L1635D 0x2415
+#define MACRONIX_MX25L1635E 0x2515 /* MX25L1635{E} */
+#define MACRONIX_MX66L51235F 0x201a /* MX66L51235F, MX25L51245G */
+#define MACRONIX_MX66L1G45G 0x201b /* MX66L1G45G */
+#define MACRONIX_MX25V4035F 0x2313
+#define MACRONIX_MX25V8035F 0x2314
+#define MACRONIX_MX25V1635F 0x2315 /* MX25V1636E */
+#define MACRONIX_MX25U8032E 0x2534
+#define MACRONIX_MX25U1635E 0x2535
+#define MACRONIX_MX25U3235E 0x2536 /* Same as MX25U6435F */
+#define MACRONIX_MX25U6435E 0x2537 /* Same as MX25U6435F */
+#define MACRONIX_MX25U12835E 0x2538 /* Same as MX25U12835F */
+#define MACRONIX_MX25U25635F 0x2539 /* Same as MX25U25643G */
+#define MACRONIX_MX25U51245G 0x253a
+#define MACRONIX_MX25L3235D 0x5E16 /* MX25L3225D/MX25L3235D/MX25L3237D */
+#define MACRONIX_MX25L6495F 0x9517
+#define MACRONIX_MX25L3255E 0x9e16
+#define MACRONIX_MX77L25650F 0x7519
+
+#define MACRONIX_MX25R3235F 0x2816
+#define MACRONIX_MX25R6435F 0x2817
+
+#define MACRONIX_MX29F001B 0x19
+#define MACRONIX_MX29F001T 0x18
+#define MACRONIX_MX29F002B 0x34 /* Same as MX29F002NB; N has reset pin n/c. */
+#define MACRONIX_MX29F002T 0xB0 /* Same as MX29F002NT; N has reset pin n/c. */
+#define MACRONIX_MX29F004B 0x46
+#define MACRONIX_MX29F004T 0x45
+#define MACRONIX_MX29F022B 0x37 /* Same as MX29F022NB */
+#define MACRONIX_MX29F022T 0x36 /* Same as MX29F022NT */
+#define MACRONIX_MX29F040 0xA4 /* Same as MX29F040C */
+#define MACRONIX_MX29F080 0xD5
+#define MACRONIX_MX29F200B 0x57 /* Same as MX29F200CB */
+#define MACRONIX_MX29F200T 0x51 /* Same as MX29F200CT */
+#define MACRONIX_MX29F400B 0xAB /* Same as MX29F400CB */
+#define MACRONIX_MX29F400T 0x23 /* Same as MX29F400CT */
+#define MACRONIX_MX29F800B 0x58
+#define MACRONIX_MX29F800T 0xD6
+#define MACRONIX_MX29GL320EB 0x7E1A00
+#define MACRONIX_MX29GL320ET 0x7E1A01
+#define MACRONIX_MX29GL320EHL 0x7E1D00
+#define MACRONIX_MX29GL640EB 0x7E1000
+#define MACRONIX_MX29GL640ET 0x7E1001
+#define MACRONIX_MX29GL640EHL 0x7E0C01
+#define MACRONIX_MX29GL128F 0x7E2101 /* Same as MX29GL128E */
+#define MACRONIX_MX29GL256F 0x7E2201 /* Same as MX29GL256E */
+#define MACRONIX_MX29GL512F 0x7E2301
+#define MACRONIX_MX68GL1G0F 0x7E2801
+#define MACRONIX_MX29LV002CB 0x5A
+#define MACRONIX_MX29LV002CT 0x59
+#define MACRONIX_MX29LV004B 0xB6 /* Same as MX29LV004CB */
+#define MACRONIX_MX29LV004T 0xB5 /* Same as MX29LV004CT */
+#define MACRONIX_MX29LV008B 0x37 /* Same as MX29LV008CB */
+#define MACRONIX_MX29LV008T 0x3E /* Same as MX29LV008CT */
+#define MACRONIX_MX29LV040 0x4F /* Same as MX29LV040C */
+#define MACRONIX_MX29LV081 0x38
+#define MACRONIX_MX29LV128DB 0x7A
+#define MACRONIX_MX29LV128DT 0x7E
+#define MACRONIX_MX29LV160DB 0x49 /* Same as MX29LV161DB/MX29LV160CB */
+#define MACRONIX_MX29LV160DT 0xC4 /* Same as MX29LV161DT/MX29LV160CT */
+#define MACRONIX_MX29LV320DB 0xA8 /* Same as MX29LV321DB */
+#define MACRONIX_MX29LV320DT 0xA7 /* Same as MX29LV321DT */
+#define MACRONIX_MX29LV400B 0xBA /* Same as MX29LV400CB */
+#define MACRONIX_MX29LV400T 0xB9 /* Same as MX29LV400CT */
+#define MACRONIX_MX29LV640DB 0xCB /* Same as MX29LV640EB */
+#define MACRONIX_MX29LV640DT 0xC9 /* Same as MX29LV640ET */
+#define MACRONIX_MX29LV800B 0x5B /* Same as MX29LV800CB */
+#define MACRONIX_MX29LV800T 0xDA /* Same as MX29LV800CT */
+#define MACRONIX_MX29SL402CB 0xF1
+#define MACRONIX_MX29SL402CT 0x70
+#define MACRONIX_MX29SL800CB 0x6B /* Same as MX29SL802CB */
+#define MACRONIX_MX29SL800CT 0xEA /* Same as MX29SL802CT */
+
+/* Nantronics Semiconductors is listed in JEP106AJ in bank 7, so it should have 6 continuation codes in front
+ * of the manufacturer ID of 0xD5. http://www.nantronicssemi.com */
+#define NANTRONICS_ID 0x7F7F7F7F7F7FD5 /* Nantronics */
+#define NANTRONICS_ID_NOPREFIX 0xD5 /* Nantronics, missing prefix */
+#define NANTRONICS_N25S10 0x3011
+#define NANTRONICS_N25S20 0x3012
+#define NANTRONICS_N25S40 0x3013
+#define NANTRONICS_N25S80 0x3014
+#define NANTRONICS_N25S16 0x3015
+
+/*
+ * Programmable Micro Corp is listed in JEP106W in bank 2, so it should
+ * have a 0x7F continuation code prefix.
+ * Apparently PMC was renamed to "Chingis Technology Corporation" http://www.chingistek.com which is now a
+ * subsidiary of ISSI. They continue to use the PMC manufacturer ID (instead of ISSI's) nevertheless, even for
+ * new chips with IS* model numbers.
+ */
+#define PMC_ID 0x7F9D /* PMC */
+#define PMC_ID_NOPREFIX 0x9D /* PMC, missing 0x7F prefix */
+#define PMC_PM25LD256C 0x2F
+#define PMC_PM25LD512 0x20 /* Same as Pm25LD512C, but the latter has more locking options. */
+#define PMC_PM25LD010 0x21 /* Same as Pm25LD010C, but the latter has more locking options. */
+#define PMC_PM25LD020 0x22 /* Same as Pm25LD020C, but the latter has more locking options. */
+#define PMC_PM25LQ020 0x42
+#define PMC_PM25LQ040 0x43
+#define PMC_PM25LQ080 0x44
+#define PMC_PM25LQ016 0x45
+#define PMC_PM25LQ032C 0x46
+#define PMC_PM25LV512 0x7B /* Same as Pm25LV512A */
+#define PMC_PM25LV010 0x7C /* Same as Pm25LV010A, but the former does not support RDID but RES3 only. */
+#define PMC_PM25LV020 0x7D
+#define PMC_PM25LV040 0x7E /* Same as PM25LD040(C), but the latter supports more features. */
+#define PMC_PM25LV080B 0x13
+#define PMC_PM25LV016B 0x14
+#define PMC_PM29F002T 0x1D
+#define PMC_PM29F002B 0x2D
+#define PMC_PM39LV512 0x1B /* Same as IS39LV512 */
+#define PMC_PM39F010 0x1C /* Same as Pm39LV010, IS39LV010 */
+#define PMC_PM39LV020 0x3D
+#define PMC_PM39LV040 0x3E /* Same as IS39LV040 */
+#define PMC_PM39F020 0x4D
+#define PMC_PM39F040 0x4E
+#define PMC_PM49FL002 0x6D
+#define PMC_PM49FL004 0x6E
+
+/*
+ * The Sanyo chip found so far uses SPI, first byte is manufacturer code,
+ * second byte is the device code,
+ * third byte is a dummy byte.
+ */
+#define SANYO_ID 0x62 /* Sanyo */
+#define SANYO_LE25FW203A 0x1600
+#define SANYO_LE25FW403A 0x1100
+#define SANYO_LE25FW106 0x15
+#define SANYO_LE25FW406 0x07 /* RES2 */
+#define SANYO_LE25FW418A 0x10 /* RES2 and some weird 1 byte RDID variant */
+#define SANYO_LE25FW406A 0x1A /* RES2, no datasheet */
+#define SANYO_LE25FU106B 0x1D
+#define SANYO_LE25FU206 0x44
+#define SANYO_LE25FU206A 0x0612
+#define SANYO_LE25FU406B 0x1E /* LE25FW418A without HD_READ mode option variant */
+#define SANYO_LE25FU406C 0x0613 /* Also known as LE25U40CMC apparently */
+#define SANYO_LE25FW806 0x26 /* RES2 and some weird 1 byte RDID variant */
+#define SANYO_LE25FW808 0x20 /* RES2 and some weird 1 byte RDID variant */
+
+#define SHARP_ID 0xB0 /* Sharp */
+#define SHARP_LH28F008BJ__PT 0xEC
+#define SHARP_LH28F008BJ__PB 0xED
+#define SHARP_LH28F800BV__BTL 0x4B
+#define SHARP_LH28F800BV__BV 0x4D
+#define SHARP_LH28F800BV__TV 0x4C
+#define SHARP_LHF00L02 0xC9 /* Same as LHF00L06/LHF00L07 */
+#define SHARP_LHF00L04 0xCF /* Same as LHF00L03/LHF00L05 */
+
+/* Spansion was previously a joint venture of AMD and Fujitsu. */
+#define SPANSION_ID 0x01 /* Spansion, same ID as AMD */
+/* S25 chips are SPI. The first device ID byte is memory type and
+ * the second device ID byte is memory capacity. */
+#define SPANSION_S25FL004A 0x0212
+#define SPANSION_S25FL008A 0x0213
+#define SPANSION_S25FL016A 0x0214
+#define SPANSION_S25FL032A 0x0215 /* Same as S25FL032P, but the latter supports EDI and CFI */
+#define SPANSION_S25FL064A 0x0216 /* Same as S25FL064P, but the latter supports EDI and CFI */
+#define SPANSION_S25FL128 0x2018 /* Same ID for various S25FL127S, S25FL128P, S25FL128S and S25FL129P (including dual-die S70FL256P) variants (EDI supported) */
+#define SPANSION_S25FL256 0x0219
+#define SPANSION_S25FL512 0x0220
+#define SPANSION_S25FL204 0x4013
+#define SPANSION_S25FL208 0x4014
+#define SPANSION_S25FL216 0x4015 /* Same as S25FL216K, but the latter supports OTP, 3 status regs, quad I/O, SFDP etc. */
+#define SPANSION_S25FL116K 0x4015
+#define SPANSION_S25FL132K 0x4016
+#define SPANSION_S25FL164K 0x4017
+#define SPANSION_S25FL128L 0x6018
+#define SPANSION_S25FL256L 0x6019
+#define SPANSION_S25FS128S_L 0x20180081 /* Large sectors. */
+#define SPANSION_S25FS128S_S 0x20180181 /* Small sectors. */
+#define SPANSION_S25FS256S_L 0x02190081 /* Large sectors. */
+#define SPANSION_S25FS256S_S 0x02190181 /* Small sectors. */
+#define SPANSION_S25FL128S_UL 0x20180080 /* Uniform Large (128kB) sectors */
+#define SPANSION_S25FL128S_US 0x20180180 /* Uniform Small (64kB) sectors */
+#define SPANSION_S25FL256S_UL 0x02190080 /* Uniform Large (128kB) sectors */
+#define SPANSION_S25FL256S_US 0x02190180 /* Uniform Small (64kB) sectors */
+
+/* Spansion 29GL families got a suffix indicating the process technology but share the same 3-Byte IDs. They can
+ * however be differentiated by CFI byte 45h. Some versions exist which have special top or bottom boot sectors
+ * and various WP configurations (not heeded in the table below).
+ *
+ * Suf. Process Sector Sz Rd Page Wr Page Data Width OTP Sz Min Size Max Size
+ * A 200 nm 64 kB 8 B 32 B x8/x16 256 B 16Mb/ 2MB 64Mb/ 8MB
+ * M 230 nm 64 kB 8 B 32 B x8/x16 256 B 32Mb/ 4MB 256Mb/ 32MB
+ * N* 110 nm 64 kB 16 B 32 B x8/x16 256 B 32Mb/ 4MB 64Mb/ 8MB
+ * N* 110 nm 128 kB 16 B 32 B x8/x16 256 B 128Mb/16MB 256Mb/ 64MB
+ * P 90 nm 128 kB 16 B 64 B x8/x16 256 B 128Mb/16MB 2Gb/256MB
+ * S 65 nm 128 kB 32 B 512 B x8 only 512 B 128Mb/16MB 2Gb/256MB
+ *
+ * For the N series there are two subgroups: the 4 and 8MB devices (S29GL032N, S29GL064N) have 64 kB erase
+ * sectors while the bigger chips got 128 kB sectors.
+ * Each series includes multiple models varying in speedgrade, boot block configurations etc.
+ */
+#define SPANSION_S29GL016_1 0xC4 /* Top Boot Sector, WP protects Top 2 sectors */
+#define SPANSION_S29GL016_2 0x49 /* Bottom Boot Sector, WP protects Bottom 2 sectors */
+/* Same IDs for S29GL032A, S29GL032M, S29GL032N (variations) */
+#define SPANSION_S29GL032_1289 0x7E1D00 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define SPANSION_S29GL032_3 0x7E1A01 /* Top Boot Sector, WP protects Top 2 sectors */
+#define SPANSION_S29GL032_4 0x7E1A00 /* Bottom Boot Sector, WP protects Bottom 2 sectors */
+/* Same IDs for S29GL064A, S29GL064M, S29GL064N, S29GL064S (variations) */
+#define SPANSION_S29GL064_1289 0x7E0C01 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define SPANSION_S29GL064_3 0x7E1001 /* Top Boot Sector, WP protects Top 2 sectors */
+#define SPANSION_S29GL064_4 0x7E1000 /* Bottom Boot Sector, WP protects Bottom 2 sectors */
+#define SPANSION_S29GL064_567 0x7E1301 /* x16 only, Uniform Sectors */
+
+#define SPANSION_S29GL128 0x7E2101 /* Same ID for S29GL128M, S29GL128N, S29GL128P, S29GL128S */
+#define SPANSION_S29GL256 0x7E2201 /* Same ID for S29GL256M, S29GL256N, S29GL256P, S29GL256S */
+#define SPANSION_S29GL512 0x7E2301 /* Same ID for S29GL512P, S29GL512S */
+#define SPANSION_S29GL01G 0x7E2801 /* Same ID for S29GL01GP, S29GL01GS */
+#define SPANSION_S70GL02G 0x7E4801 /* Same ID for S70GL02GP, S70GL02GS; based on two S29GL01G dies respectively */
+
+/*
+ * SST25 chips are SPI, first byte of device ID is memory type, second
+ * byte of device ID is related to log(bitsize) at least for some chips.
+ */
+#define SST_ID 0xBF /* SST */
+#define SST_SST25LF020_REMS 0x43 /* REMS or RES opcode */
+#define SST_SST25WF512 0x2501
+#define SST_SST25WF010 0x2502
+#define SST_SST25WF020 0x2503
+#define SST_SST25WF040 0x2504
+#define SST_SST25WF080 0x2505
+/* There exist some successors to members of the SST25WF family with alphabetic suffixes. Their datasheets show
+ * a 4 byte long response w/o a vendor ID. The first byte is 0x62 that is actually Sanyo's and might be due to
+ * a collaboration in the mid 2000ies between Sanyo and SST. */
+#define SST_SST25WF020A 0x1612
+#define SST_SST25WF040B 0x1613
+#define SST_SST25WF080B 0x1614
+#define SST_SST25VF512_REMS 0x48 /* REMS or RES opcode, same as SST25VF512A */
+#define SST_SST25VF010_REMS 0x49 /* REMS or RES opcode, same as SST25VF010A */
+#define SST_SST25VF020_REMS 0x43 /* REMS or RES opcode, same as SST25LF020A */
+#define SST_SST25VF020B 0x258C
+#define SST_SST25VF040_REMS 0x44 /* REMS or RES opcode, same as SST25LF040A */
+#define SST_SST25VF040B 0x258D
+#define SST_SST25VF040B_REMS 0x8D /* REMS or RES opcode */
+#define SST_SST25VF080_REMS 0x80 /* REMS or RES opcode, same as SST25LF080A */
+#define SST_SST25VF080B 0x258E
+#define SST_SST25VF080B_REMS 0x8E /* REMS or RES opcode */
+#define SST_SST25VF016B 0x2541
+#define SST_SST25VF032B 0x254A
+#define SST_SST25VF032B_REMS 0x4A /* REMS or RES opcode */
+#define SST_SST25VF064C 0x254B
+#define SST_SST26VF016 0x2601
+#define SST_SST26VF032 0x2602
+#define SST_SST26VF016B 0x2641
+#define SST_SST26VF032B 0x2642
+#define SST_SST26VF064B 0x2643
+#define SST_SST27SF512 0xA4
+#define SST_SST27SF010 0xA5
+#define SST_SST27SF020 0xA6
+#define SST_SST27VF010 0xA9
+#define SST_SST27VF020 0xAA
+#define SST_SST28SF040 0x04
+#define SST_SST29LE512 0x3D /* Same as SST29VE512 */
+#define SST_SST29EE512 0x5D
+#define SST_SST29EE010 0x07
+#define SST_SST29LE010 0x08 /* Same as SST29VE010 */
+#define SST_SST29EE020A 0x10 /* Same as SST29EE020 */
+#define SST_SST29LE020 0x12 /* Same as SST29VE020 */
+#define SST_SST29SF020 0x24
+#define SST_SST29VF020 0x25
+#define SST_SST29SF040 0x13
+#define SST_SST29VF040 0x14
+#define SST_SST39SF512 0xB4
+#define SST_SST39SF010 0xB5
+#define SST_SST39SF020 0xB6 /* Same as 39SF020A */
+#define SST_SST39SF040 0xB7
+#define SST_SST39VF512 0xD4
+#define SST_SST39VF010 0xD5
+#define SST_SST39VF020 0xD6 /* Same as 39LF020 */
+#define SST_SST39VF040 0xD7 /* Same as 39LF040 */
+#define SST_SST39VF080 0xD8 /* Same as 39LF080/39VF080/39VF088 */
+#define SST_SST45VF512 0x41 /* REMS, read opcode 0xFF */
+#define SST_SST45LF010 0x42 /* REMS, read opcode 0xFF, 'funny' other opcodes */
+#define SST_SST45VF010 0x45 /* REMS, read opcode 0xFF */
+#define SST_SST45VF020 0x43 /* REMS, read opcode 0xFF */
+#define SST_SST49LF040B 0x50
+#define SST_SST49LF040 0x51
+#define SST_SST49LF020 0x61
+#define SST_SST49LF020A 0x52
+#define SST_SST49LF030A 0x1C
+#define SST_SST49LF080A 0x5B
+#define SST_SST49LF002A 0x57
+#define SST_SST49LF003A 0x1B
+#define SST_SST49LF004A 0x60 /* Same as 49LF004B */
+#define SST_SST49LF008A 0x5A
+#define SST_SST49LF004C 0x54
+#define SST_SST49LF008C 0x59
+#define SST_SST49LF016C 0x5C
+#define SST_SST49LF160C 0x4C
+
+/*
+ * ST25P chips are SPI, first byte of device ID is memory type, second
+ * byte of device ID is related to log(bitsize) at least for some chips.
+ */
+#define ST_ID 0x20 /* ST / SGS/Thomson / Numonyx / XMC(later acquired by Micron) */
+#define ST_M25P05A 0x2010
+#define ST_M25P05_RES 0x05
+#define ST_M25P10A 0x2011
+#define ST_M25P10_RES 0x10
+#define ST_M25P20 0x2012
+#define ST_M25P20_RES 0x11
+#define ST_M25P40 0x2013
+#define ST_M25P40_RES 0x12
+#define ST_M25P80 0x2014
+#define ST_M25P16 0x2015
+#define ST_M25P32 0x2016
+#define ST_M25P64 0x2017
+#define ST_M25P128 0x2018
+#define ST_M45PE10 0x4011
+#define ST_M45PE20 0x4012
+#define ST_M45PE40 0x4013
+#define ST_M45PE80 0x4014 /* Same as XM25QH80B */
+#define ST_M45PE16 0x4015
+#define XMC_XM25QH64C 0x4017
+#define XMC_XM25QU64C 0x4117
+#define XMC_XM25QH128A 0x7018
+#define XMC_XM25QH128C 0x4018
+#define XMC_XM25QU128C 0x4118
+#define XMC_XM25QH256C 0x4019
+#define XMC_XM25QU256C 0x4119
+#define ST_M25PX80 0x7114
+#define ST_M25PX16 0x7115
+#define ST_M25PX32 0x7116
+#define ST_M25PX64 0x7117
+#define ST_M25PE10 0x8011
+#define ST_M25PE20 0x8012
+#define ST_M25PE40 0x8013
+#define ST_M25PE80 0x8014
+#define ST_M25PE16 0x8015
+#define ST_M50FLW040A 0x08
+#define ST_M50FLW040B 0x28
+#define ST_M50FLW080A 0x80
+#define ST_M50FLW080B 0x81
+#define ST_M50FW002 0x29
+#define ST_M50FW040 0x2C
+#define ST_M50FW080 0x2D
+#define ST_M50FW016 0x2E
+#define ST_M50LPW080 0x2F
+#define ST_M50LPW116 0x30
+#define ST_M29F002B 0x34 /* Same as M29F002BB */
+#define ST_M29F002T 0xB0 /* Same as M29F002BT/M29F002NT/M29F002BNT */
+#define ST_M29F040B 0xE2 /* Same as M29F040 */
+#define ST_M29F080 0xF1
+#define ST_M29F200BT 0xD3
+#define ST_M29F200BB 0xD4
+#define ST_M29F400BT 0xD5 /* Same as M29F400T */
+#define ST_M29F400BB 0xD6 /* Same as M29F400B */
+#define ST_M29F800DB 0x58
+#define ST_M29F800DT 0xEC
+#define ST_M29W010B 0x23
+#define ST_M29W040B 0xE3
+#define ST_M29W512B 0x27
+#define ST_M28W160ECB 0x88CF
+#define ST_M28W160ECT 0x88CE
+#define ST_M28W320FCB 0x88BB
+#define ST_M28W320FCT 0x88BA
+#define ST_M28W640HCB 0x8849
+#define ST_M28W640HCT 0x8848
+#define ST_M29DW127G 0x7E2004
+#define ST_M29W128GH 0x7E2101
+#define ST_M29W128GL 0x7E2100
+#define ST_M29W160EB 0x2249
+#define ST_M29W160ET 0x22C4
+#define ST_M29W256GH 0x7E21xx
+#define ST_M29W256GL 0x7E21xx
+#define ST_M29W320DB 0x88CB
+#define ST_M29W320DT 0x88CA
+#define ST_M29W400FB 0x00EF
+#define ST_M29W400FT 0x00EE
+#define ST_M29W512GH 0x7E2301
+#define ST_M29W640FB 0x22FD
+#define ST_M29W640FT 0x22ED
+#define ST_M29W640GB 0x7E1000
+#define ST_M29W640GH 0x7E0C01
+#define ST_M29W640GL 0x7E0C00
+#define ST_M29W640GT 0x7E1001
+#define ST_M29W800FB 0x225B
+#define ST_M29W800FT 0x22D7
+#define ST_M58BW16FB 0x8839
+#define ST_M58BW16FT 0x883A
+#define ST_M58BW32FB 0x8837
+#define ST_M58BW32FT 0x8838
+#define ST_M58WR016KB 0x8813
+#define ST_M58WR016KT 0x8812
+#define ST_M58WR032KB 0x8815
+#define ST_M58WR032KT 0x8814
+#define ST_M58WR064KB 0x8811
+#define ST_M58WR064KT 0x8810
+
+#define ST_M95M02 0x0012 /* ST M95XXX 2Mbit (256KiB) */
+
+#define ST_MT28GU01G___1 0x88B0
+#define ST_MT28GU01G___2 0x88B1
+#define ST_MT28GU256___1 0x8901
+#define ST_MT28GU256___2 0x8904
+#define ST_MT28GU512___1 0x887E
+#define ST_MT28GU512___2 0x8881
+#define ST_N25Q016__1E 0xBB15 /* N25Q016, 1.8V, (uniform sectors expected) */
+#define ST_N25Q032__3E 0xBA16 /* N25Q032, 3.0V, (uniform sectors expected) */
+#define ST_N25Q032__1E 0xBB16 /* N25Q032, 1.8V, (uniform sectors expected) */
+#define ST_N25Q064__3E 0xBA17 /* N25Q064, 3.0V, (uniform sectors expected) */
+#define ST_N25Q064__1E 0xBB17 /* N25Q064, 1.8V, (uniform sectors expected) */
+#define ST_N25Q128__3E 0xBA18 /* N25Q128/MT25QL128, 3.0V, (uniform sectors expected) */
+#define ST_N25Q128__1E 0xBB18 /* N25Q128/MT25QU128, 1.8V, (uniform sectors expected) */
+#define ST_N25Q256__3E 0xBA19 /* N25Q256/MT25QL256, 3.0V, (uniform sectors expected) */
+#define ST_N25Q256__1E 0xBB19 /* N25Q256/MT25QU256, 1.8V, (uniform sectors expected) */
+#define ST_N25Q512__3G 0xBA20 /* N25Q512/MT25QL512, 3.0V, (uniform sectors expected) */
+#define ST_N25Q512__1G 0xBB20 /* N25Q512/MT25QU512, 1.8V, (uniform sectors expected) */
+#define ST_N25Q00A__3G 0xBA21 /* N25Q00A/MT25QL01G, 3.0V, (uniform sectors expected) */
+#define ST_N25Q00A__1G 0xBB21 /* N25Q00A/MT25QU01G, 1.8V, (uniform sectors expected) */
+#define ST_MT25QL02G 0xBA22 /* MT25QL02G, 3.0V, (uniform sectors expected) */
+#define ST_MT25QU02G 0xBB22 /* MT25QU02G, 1.8V, (uniform sectors expected) */
+#define ST_NP5Q032 0xDA16 /* Phase-change memory (PCM), 3V */
+#define ST_NP5Q064 0xDA17 /* Phase-change memory (PCM), 3V */
+#define ST_NP5Q128 0xDA18 /* Phase-change memory (PCM), 3V */
+
+#define SYNCMOS_MVC_ID 0x40 /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */
+#define MVC_V29C51000T 0x00
+#define MVC_V29C51400T 0x13
+#define MVC_V29LC51000 0x20
+#define MVC_V29LC51001 0x60
+#define MVC_V29LC51002 0x82
+#define MVC_V29C51000B 0xA0
+#define MVC_V29C51400B 0xB3
+#define SM_MVC_29C51001T 0x01 /* Identical chips: {F,S,V}29C51001T */
+#define SM_MVC_29C51002T 0x02 /* Identical chips: {F,S,V}29C51002T */
+#define SM_MVC_29C51004T 0x03 /* Identical chips: {F,S,V}29C51004T */
+#define SM_MVC_29C31004T 0x63 /* Identical chips: {S,V}29C31004T */
+#define SM_MVC_29C31004B 0x73 /* Identical chips: {S,V}29C31004B */
+#define SM_MVC_29C51001B 0xA1 /* Identical chips: {F,S,V}29C51001B */
+#define SM_MVC_29C51002B 0xA2 /* Identical chips: {F,S,V}29C51002B */
+#define SM_MVC_29C51004B 0xA3 /* Identical chips: {F,S,V}29C51004B */
+
+#define TENX_ID 0x7F7F5E /* Tenx Technologies */
+#define TENX_ID_NOPREFIX 0x5E
+#define TENX_ICE25P05 0x01 /* Maybe? */
+
+#define TI_ID 0x97 /* Texas Instruments */
+#define TI_OLD_ID 0x01 /* TI chips from last century */
+#define TI_TMS29F002RT 0xB0
+#define TI_TMS29F002RB 0x34
+
+/*
+ * W25X chips are SPI, first byte of device ID is memory type, second
+ * byte of device ID is related to log(bitsize).
+ */
+#define WINBOND_NEX_ID 0xEF /* Winbond (ex Nexcom) serial flashes */
+#define WINBOND_NEX_W25P80 0x2014
+#define WINBOND_NEX_W25P16 0x2015
+#define WINBOND_NEX_W25P32 0x2016
+#define WINBOND_NEX_W25X05 0x3010 /* W25X05CL */
+#define WINBOND_NEX_W25X10 0x3011
+#define WINBOND_NEX_W25X20 0x3012
+#define WINBOND_NEX_W25X40 0x3013
+#define WINBOND_NEX_W25X80 0x3014
+#define WINBOND_NEX_W25X16 0x3015
+#define WINBOND_NEX_W25X32 0x3016
+#define WINBOND_NEX_W25X64 0x3017
+#define WINBOND_NEX_W25Q40_V 0x4013 /* W25Q40BV; W25Q40BL (2.3-3.6V) */
+#define WINBOND_NEX_W25Q80_V 0x4014 /* W25Q80BV */
+#define WINBOND_NEX_W25Q16_V 0x4015 /* W25Q16CV; W25Q16DV */
+#define WINBOND_NEX_W25Q32_V 0x4016 /* W25Q32BV; W25Q32FV in SPI mode (default) */
+#define WINBOND_NEX_W25Q64_V 0x4017 /* W25Q64BV, W25Q64CV; W25Q64FV in SPI mode (default) */
+#define WINBOND_NEX_W25Q128_V 0x4018 /* W25Q128BV; W25Q128FV in SPI mode (default) */
+#define WINBOND_NEX_W25Q256_V 0x4019 /* W25Q256FV or W25Q256JV_Q (QE=1) */
+#define WINBOND_NEX_W25Q512JV 0x4020 /* W25Q512JV */
+#define WINBOND_NEX_W25Q20_W 0x5012 /* W25Q20BW */
+#define WINBOND_NEX_W25Q40BW 0x5013 /* W25Q40BW */
+#define WINBOND_NEX_W25Q80BW 0x5014 /* W25Q80BW */
+#define WINBOND_NEX_W25Q40EW 0x6013 /* W25Q40EW */
+#define WINBOND_NEX_W25Q80EW 0x6014 /* W25Q80EW */
+#define WINBOND_NEX_W25Q16_W 0x6015 /* W25Q16DW */
+#define WINBOND_NEX_W25Q32_W 0x6016 /* W25Q32DW; W25Q32FV in QPI mode */
+#define WINBOND_NEX_W25Q64_W 0x6017 /* W25Q64DW; W25Q64FV in QPI mode */
+#define WINBOND_NEX_W25Q128_W 0x6018 /* W25Q128FW; W25Q128FV in QPI mode */
+#define WINBOND_NEX_W25Q256_W 0x6019 /* W25Q256JW */
+#define WINBOND_NEX_W25Q64JV 0x7017 /* W25Q64JV */
+#define WINBOND_NEX_W25Q128_V_M 0x7018 /* W25Q128JVSM */
+#define WINBOND_NEX_W25Q256JV_M 0x7019 /* W25Q256JV_M (QE=0) */
+#define WINBOND_NEX_W25Q32JW_M 0x8016 /* W25Q32JW...M */
+#define WINBOND_NEX_W25Q64JW_M 0x8017 /* W25Q64JW...M */
+#define WINBOND_NEX_W25Q128_DTR 0x8018 /* W25Q128JW_DTR */
+#define WINBOND_NEX_W25Q256_DTR 0x8019 /* W25Q256JW_DTR aka W25Q256256JW-IM */
+#define WINBOND_NEX_W25Q512NW_IM 0x8020 /* W25Q512NW-IM */
+
+#define WINBOND_ID 0xDA /* Winbond */
+#define WINBOND_W19B160BB 0x49
+#define WINBOND_W19B160BT 0xC4
+#define WINBOND_W19B320SB 0x2A /* Same as W19L320SB */
+#define WINBOND_W19B320ST 0xBA /* Same as W19L320ST */
+#define WINBOND_W19B322MB 0x92
+#define WINBOND_W19B322MT 0x10
+#define WINBOND_W19B323MB 0x94
+#define WINBOND_W19B323MT 0x13
+#define WINBOND_W19B324MB 0x97
+#define WINBOND_W19B324MT 0x16
+#define WINBOND_W29C010 0xC1 /* Same as W29C010M, W29C011A, W29EE011, W29EE012, and ASD AE29F1008 */
+#define WINBOND_W29C020 0x45 /* Same as W29C020C, W29C022 and ASD AE29F2008 */
+#define WINBOND_W29C040 0x46 /* Same as W29C040P */
+#define WINBOND_W29C512A 0xC8 /* Same as W29EE512 */
+#define WINBOND_W29GL032CHL 0x7E1D01 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define WINBOND_W29GL032CB 0x7E1A00 /* Top Boot Sector, WP protects Top 2 sectors */
+#define WINBOND_W29GL032CT 0x7E1A01 /* Bottom Boot Sector, WP protects Bottom 2 sectors */
+#define WINBOND_W29GL064CHL 0x7E0C01 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define WINBOND_W29GL064CB 0x7E1000 /* Top Boot Sector, WP protects Top 2 sectors */
+#define WINBOND_W29GL064CT 0x7E1001 /* Bottom Boot Sector, WP protects Bottom 2 sectors */
+#define WINBOND_W29GL128CHL 0x7E2101 /* Uniform Sectors, WP protects Top OR Bottom sector */
+#define WINBOND_W29GL256HL 0x7E2201 /* Same ID for W29GL0256P and W29GL0256S; uniform Sectors, WP protects Top OR Bottom sector */
+#define WINBOND_W39F010 0xA1
+#define WINBOND_W39L010 0x31
+#define WINBOND_W39L020 0xB5
+#define WINBOND_W39L040 0xB6
+#define WINBOND_W39L040A 0xD6
+#define WINBOND_W39L512 0x38
+#define WINBOND_W39V040A 0x3D
+#define WINBOND_W39V040FA 0x34
+#define WINBOND_W39V040B 0x54 /* Same as W39V040FB */
+#define WINBOND_W39V040C 0x50 /* Same as W39V040FC */
+#define WINBOND_W39V080A 0xD0
+#define WINBOND_W39V080FA 0xD3
+#define WINBOND_W39V080FA_DM 0x93 /* W39V080FA dual mode */
+#define WINBOND_W49F002 0x25 /* Same as W49F002B */
+#define WINBOND_W49F002U 0x0B /* Same as W49F002N and ASD AE49F2008 */
+#define WINBOND_W49F020 0x8C
+#define WINBOND_W49V002A 0xB0
+#define WINBOND_W49V002FA 0x32
+
+#define XTX_ID 0x0B /* XTX Technology Limited */
+#define XTX_XT25F02E 0x4012
+#define XTX_XT25F64B 0x4017
+
+#define ZETTADEVICE_ID 0xBA /* Zetta Device */
+#define ZETTADEVICE_ZD25D20 0x2012
+#define ZETTADEVICE_ZD25D40 0x2013
+
+#endif /* !FLASHCHIPS_H */
diff --git a/include/fmap.h b/include/fmap.h
new file mode 100644
index 000000000..924e11f6b
--- /dev/null
+++ b/include/fmap.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010, Google LLC.
+ * Copyright 2018-present, Facebook Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#ifndef __FMAP_H__
+#define __FMAP_H__ 1
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#define FMAP_SIGNATURE "__FMAP__"
+#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */
+#define FMAP_VER_MINOR 1 /* this header's FMAP minor version */
+#define FMAP_STRLEN 32 /* maximum length for strings */
+
+struct fmap_area {
+ uint32_t offset; /* offset relative to base */
+ uint32_t size; /* size in bytes */
+ uint8_t name[FMAP_STRLEN]; /* descriptive name */
+ uint16_t flags; /* flags for this area */
+} __attribute__((packed));
+
+struct fmap {
+ uint8_t signature[8]; /* "__FMAP__" */
+ uint8_t ver_major; /* major version */
+ uint8_t ver_minor; /* minor version */
+ uint64_t base; /* address of the firmware binary */
+ uint32_t size; /* size of firmware binary in bytes */
+ uint8_t name[FMAP_STRLEN]; /* name of this firmware binary */
+ uint16_t nareas; /* number of areas described by
+ fmap_areas[] below */
+ struct fmap_area areas[];
+} __attribute__((packed));
+
+int fmap_read_from_buffer(struct fmap **fmap_out, const uint8_t *buf, size_t len);
+int fmap_read_from_rom(struct fmap **fmap_out, struct flashctx *const flashctx, size_t rom_offset, size_t len);
+
+
+#endif /* __FMAP_H__*/
diff --git a/include/hwaccess_physmap.h b/include/hwaccess_physmap.h
new file mode 100644
index 000000000..a0a7e74d8
--- /dev/null
+++ b/include/hwaccess_physmap.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __HWACCESS_PHYSMAP_H__
+#define __HWACCESS_PHYSMAP_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+void *physmap(const char *descr, uintptr_t phys_addr, size_t len);
+void *rphysmap(const char *descr, uintptr_t phys_addr, size_t len);
+void *physmap_ro(const char *descr, uintptr_t phys_addr, size_t len);
+void *physmap_ro_unaligned(const char *descr, uintptr_t phys_addr, size_t len);
+void physunmap(void *virt_addr, size_t len);
+void physunmap_unaligned(void *virt_addr, size_t len);
+
+void mmio_writeb(uint8_t val, void *addr);
+void mmio_writew(uint16_t val, void *addr);
+void mmio_writel(uint32_t val, void *addr);
+uint8_t mmio_readb(const void *addr);
+uint16_t mmio_readw(const void *addr);
+uint32_t mmio_readl(const void *addr);
+void mmio_readn(const void *addr, uint8_t *buf, size_t len);
+void mmio_le_writeb(uint8_t val, void *addr);
+void mmio_le_writew(uint16_t val, void *addr);
+void mmio_le_writel(uint32_t val, void *addr);
+uint8_t mmio_le_readb(const void *addr);
+uint16_t mmio_le_readw(const void *addr);
+uint32_t mmio_le_readl(const void *addr);
+#define pci_mmio_writeb mmio_le_writeb
+#define pci_mmio_writew mmio_le_writew
+#define pci_mmio_writel mmio_le_writel
+#define pci_mmio_readb mmio_le_readb
+#define pci_mmio_readw mmio_le_readw
+#define pci_mmio_readl mmio_le_readl
+void rmmio_writeb(uint8_t val, void *addr);
+void rmmio_writew(uint16_t val, void *addr);
+void rmmio_writel(uint32_t val, void *addr);
+void rmmio_le_writeb(uint8_t val, void *addr);
+void rmmio_le_writew(uint16_t val, void *addr);
+void rmmio_le_writel(uint32_t val, void *addr);
+#define pci_rmmio_writeb rmmio_le_writeb
+#define pci_rmmio_writew rmmio_le_writew
+#define pci_rmmio_writel rmmio_le_writel
+void rmmio_valb(void *addr);
+void rmmio_valw(void *addr);
+void rmmio_vall(void *addr);
+
+#endif /* __HWACCESS_PHYSMAP_H__ */ \ No newline at end of file
diff --git a/include/hwaccess_x86_io.h b/include/hwaccess_x86_io.h
new file mode 100644
index 000000000..31d1e86c8
--- /dev/null
+++ b/include/hwaccess_x86_io.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2022 secunet Security Networks AG
+ * (Written by Thomas Heijligen <thomas.heijligen@secunet.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * This file contains prototypes for x86 I/O Port access.
+ */
+
+#ifndef __HWACCESS_X86_IO_H__
+#define __HWACCESS_X86_IO_H__ 1
+
+#include <stdint.h>
+/**
+ */
+int rget_io_perms(void);
+
+void OUTB(uint8_t value, uint16_t port);
+void OUTW(uint16_t value, uint16_t port);
+void OUTL(uint32_t value, uint16_t port);
+uint8_t INB(uint16_t port);
+uint16_t INW(uint16_t port);
+uint32_t INL(uint16_t port);
+
+#endif /* __HWACCESS_X86_IO_H__ */
diff --git a/include/hwaccess_x86_msr.h b/include/hwaccess_x86_msr.h
new file mode 100644
index 000000000..eda007e80
--- /dev/null
+++ b/include/hwaccess_x86_msr.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __HWACCESS_X86_MSR_H__
+#define __HWACCESS_X86_MSR_H__ 1
+
+#include <stdint.h>
+
+typedef struct { uint32_t hi, lo; } msr_t;
+
+msr_t msr_read(int addr);
+int msr_write(int addr, msr_t msr);
+int msr_setup(int cpu);
+void msr_cleanup(void);
+
+#endif /* __HWACCESS_X86_MSR_H__ */ \ No newline at end of file
diff --git a/include/i2c_helper.h b/include/i2c_helper.h
new file mode 100644
index 000000000..b840b3a9d
--- /dev/null
+++ b/include/i2c_helper.h
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2020 The Chromium OS Authors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef I2C_HELPER_H
+#define I2C_HELPER_H
+
+#include <inttypes.h>
+
+struct programmer_cfg; /* defined in programmer.h */
+
+/**
+ * An convenient structure that contains the buffer size and the buffer
+ * pointer. Used to wrap buffer details while doing the I2C data
+ * transfer on both input and output. It is the client's responsibility
+ * to use i2c_buffer_t_fill to initialize this struct instead of
+ * trying to construct it directly.
+ */
+typedef struct {
+ void *buf;
+ uint16_t len;
+} i2c_buffer_t;
+
+/**
+ * i2c_buffer_t_fill - fills in the i2c_buffer_t
+ *
+ * @i2c_buf: pointer to the be constructed.
+ * @buf: buffer contains data to be included in i2c_buffer_t.
+ * @len: length of buffer to be included in i2c_buffer_t.
+ *
+ * This function takes in a pointer to an initialized i2c_buffer_t
+ * object with related information, and fill in the i2c_buffer_t with
+ * some validation applied. The function does allow initialization with
+ * NULL buffer but will make sure len == 0 in such case.
+ *
+ * returns 0 on success, <0 to indicate failure
+ */
+static inline int i2c_buffer_t_fill(i2c_buffer_t *i2c_buf, void *buf, uint16_t len)
+{
+ if (!i2c_buf || (!buf && len))
+ return -1;
+
+ i2c_buf->buf = buf;
+ i2c_buf->len = len;
+
+ return 0;
+}
+
+/**
+ * i2c_open - opens the target I2C device and set the I2C slave address
+ *
+ * @bus: I2C bus number of the target device.
+ * @addr: I2C slave address.
+ * @force: whether to force set the I2C slave address.
+ *
+ * This function returns a file descriptor for the target device. It is
+ * the client's responsibility to pass the return value to i2c_close to
+ * clean up.
+ *
+ * returns fd of target device on success, <0 to indicate failure
+ */
+int i2c_open(int bus, uint16_t addr, int force);
+
+/**
+ * i2c_open_path: open an I2C device by device path
+ *
+ * This function behaves the same as i2c_open, but takes a filesystem
+ * path (assumed to be an I2C device file) instead of a bus number.
+ */
+int i2c_open_path(const char *path, uint16_t addr, int force);
+
+/**
+ * i2c_open_from_programmer_params: open an I2C device from programmer params
+ *
+ * This function is a wrapper for i2c_open and i2c_open_path that obtains the
+ * I2C device to use from programmer parameters. It is meant to be called
+ * from I2C-based programmers to avoid repeating parameter parsing code.
+ */
+int i2c_open_from_programmer_params(const struct programmer_cfg *cfg, uint16_t addr, int force);
+
+/**
+ * i2c_close - closes the file descriptor returned by i2c_open
+ *
+ * @fd: file descriptor to be closed.
+ *
+ * It is the client's responsibility to set fd = -1 when it is
+ * done with it.
+ *
+ * returns 0 on success, <0 to indicate failure
+ */
+int i2c_close(int fd);
+
+/**
+ * i2c_read - reads data from the I2C device
+ *
+ * @fd: file descriptor of the target device.
+ * @addr: I2C slave address of the target device.
+ * @buf_read: data struct includes reading buffer and size.
+ *
+ * This function does accept empty read and do nothing on such case.
+ *
+ * returns read length on success, <0 to indicate failure
+ */
+int i2c_read(int fd, uint16_t addr, i2c_buffer_t *buf_read);
+
+/**
+ * i2c_write - writes command/data into the I2C device
+ *
+ * @fd: file descriptor of the target device.
+ * @addr: I2C slave address of the target device.
+ * @buf_write: data struct includes writing buffer and size.
+ *
+ * This function does accept empty write and do nothing on such case.
+ *
+ * returns wrote length on success, <0 to indicate failure.
+ */
+int i2c_write(int fd, uint16_t addr, const i2c_buffer_t *buf_write);
+
+#endif /* !I2C_HELPER_H */
diff --git a/include/ich_descriptors.h b/include/ich_descriptors.h
new file mode 100644
index 000000000..5a6cdf10c
--- /dev/null
+++ b/include/ich_descriptors.h
@@ -0,0 +1,596 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (c) 2010 Matthias Wenzel <bios at mazzoo dot de>
+ * Copyright (c) 2011 Stefan Tauner
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ICH_DESCRIPTORS_H__
+#define __ICH_DESCRIPTORS_H__ 1
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "programmer.h" /* for enum ich_chipset */
+
+/* FIXME: Replace with generic return codes */
+#define ICH_RET_OK 0
+#define ICH_RET_ERR -1
+#define ICH_RET_WARN -2
+#define ICH_RET_PARAM -3
+#define ICH_RET_OOB -4
+
+#define ICH9_REG_FDOC 0xB0 /* 32 Bits Flash Descriptor Observability Control */
+#define PCH100_REG_FDOC 0xB4 /* New offset from Sunrise Point on */
+ /* 0-1: reserved */
+#define FDOC_FDSI_OFF 2 /* 2-11: Flash Descriptor Section Index */
+#define FDOC_FDSI (0x3f << FDOC_FDSI_OFF)
+#define FDOC_FDSS_OFF 12 /* 12-14: Flash Descriptor Section Select */
+#define FDOC_FDSS (0x3 << FDOC_FDSS_OFF)
+ /* 15-31: reserved */
+
+#define ICH9_REG_FDOD 0xB4 /* 32 Bits Flash Descriptor Observability Data */
+#define PCH100_REG_FDOD 0xB8 /* New offset from Sunrise Point on */
+
+/* Field locations and semantics for LVSCC, UVSCC and related words in the flash
+ * descriptor are equal therefore they all share the same macros below. */
+#define VSCC_BES_OFF 0 /* 0-1: Block/Sector Erase Size */
+#define VSCC_BES (0x3 << VSCC_BES_OFF)
+#define VSCC_WG_OFF 2 /* 2: Write Granularity */
+#define VSCC_WG (0x1 << VSCC_WG_OFF)
+#define VSCC_WSR_OFF 3 /* 3: Write Status Required */
+#define VSCC_WSR (0x1 << VSCC_WSR_OFF)
+#define VSCC_WEWS_OFF 4 /* 4: Write Enable on Write Status */
+#define VSCC_WEWS (0x1 << VSCC_WEWS_OFF)
+ /* 5-7: reserved */
+#define VSCC_EO_OFF 8 /* 8-15: Erase Opcode */
+#define VSCC_EO (0xff << VSCC_EO_OFF)
+ /* 16-22: reserved */
+#define VSCC_VCL_OFF 23 /* 23: Vendor Component Lock */
+#define VSCC_VCL (0x1 << VSCC_VCL_OFF)
+ /* 24-31: reserved */
+
+#define ICH_FREG_BASE(flreg) (((flreg) << 12) & 0x07fff000)
+#define ICH_FREG_LIMIT(flreg) ((((flreg) >> 4) & 0x07fff000) | 0x00000fff)
+
+void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl);
+
+struct ich_desc_content {
+ uint32_t FLVALSIG; /* 0x00 */
+ union { /* 0x04 */
+ uint32_t FLMAP0;
+ struct {
+ uint32_t FCBA :8, /* Flash Component Base Address */
+ NC :2, /* Number Of Components */
+ :6,
+ FRBA :8, /* Flash Region Base Address */
+ NR :3, /* Number Of Regions (reserved from Skylake on) */
+ :5;
+ };
+ };
+ union { /* 0x08 */
+ uint32_t FLMAP1;
+ struct {
+ uint32_t FMBA :8, /* Flash Master Base Address */
+ NM :3, /* Number Of Masters */
+ :5,
+ FISBA :8, /* Flash ICH Strap Base Address */
+ ISL :8; /* ICH Strap Length */
+ };
+ };
+ union { /* 0x0c */
+ uint32_t FLMAP2;
+ struct {
+ uint32_t FMSBA :8, /* Flash (G)MCH Strap Base Addr. */
+ MSL :8, /* MCH Strap Length */
+ ICCRIBA :8, /* ICC Reg. Init Base Addr. (new since Sandy Bridge) */
+ RIL :8; /* Register Init Length (new since Hawell) */
+ };
+ struct { /* new since Tiger Point */
+ uint32_t :2,
+ CSSO :10, /* CPU Soft Strap Offset from PMC Base */
+ :4,
+ CSSL :8, /* CPU Soft Strap Length */
+ :8;
+ };
+ };
+};
+
+struct ich_desc_component {
+ union { /* 0x00 */
+ uint32_t FLCOMP; /* Flash Components Register */
+ /* FLCOMP encoding on various generations:
+ *
+ * Chipset/Generation max_speed dual_output density
+ * [MHz] bits max. bits
+ * ICH8: 33 N/A 5 0:2, 3:5
+ * ICH9: 33 N/A 5 0:2, 3:5
+ * ICH10: 33 N/A 5 0:2, 3:5
+ * Ibex Peak/5: 50 N/A 5 0:2, 3:5
+ * Cougar Point/6: 50 30 5 0:2, 3:5
+ * Patsburg: 50 30 5 0:2, 3:5
+ * Panther Point/7 50 30 5 0:2, 3:5
+ * Lynx Point/8: 50 30 7 0:3, 4:7
+ * Wildcat Point/9: 50 30 (multi I/O) 7 0:3, 4:7
+ * Sunrise Point/100: 48 30 7 0:3, 4:7
+ */
+ struct {
+ uint32_t :17,
+ freq_read :3,
+ fastread :1,
+ freq_fastread :3,
+ freq_write :3,
+ freq_read_id :3,
+ dual_output :1, /* new since Cougar Point/6 */
+ :1;
+ } modes;
+ struct {
+ uint32_t comp1_density :3,
+ comp2_density :3,
+ :26;
+ } dens_old;
+ struct {
+ uint32_t comp1_density :4, /* new since Lynx Point/8 */
+ comp2_density :4,
+ :24;
+ } dens_new;
+ };
+ union { /* 0x04 */
+ uint32_t FLILL; /* Flash Invalid Instructions Register */
+ struct {
+ uint32_t invalid_instr0 :8,
+ invalid_instr1 :8,
+ invalid_instr2 :8,
+ invalid_instr3 :8;
+ };
+ };
+ union { /* 0x08 */
+ uint32_t FLPB; /* Flash Partition Boundary Register, until Panther Point/7 */
+ struct {
+ uint32_t FPBA :13, /* Flash Partition Boundary Addr */
+ :19;
+ };
+ uint32_t FLILL1; /* Flash Invalid Instructions Register, new since Sunrise Point/100 */
+ struct {
+ uint32_t invalid_instr4 :8,
+ invalid_instr5 :8,
+ invalid_instr6 :8,
+ invalid_instr7 :8;
+ };
+ };
+};
+
+#define MAX_NUM_FLREGS 16
+struct ich_desc_region {
+ /*
+ * Number of entries and width differ on various generations:
+ *
+ * Chipset/Generation #FLREGs width (bits)
+ * ICH8 .. Panther Point/7 5 13
+ * Lynx Point/8 .. Wildcat Point/9 7 15
+ * Sunrise Point/100 .. 200 Series 10 15
+ * Lewisburg/100 .. 16 15
+ * Cannon Point/300 .. 16 15
+ */
+ union {
+ uint32_t FLREGs[MAX_NUM_FLREGS]; /* Flash Descriptor Regions */
+
+ /* only used for bit-field check */
+ struct {
+ uint32_t base :13,
+ :3,
+ limit :13,
+ :3;
+ } old_reg[MAX_NUM_FLREGS];
+ };
+};
+
+#define MAX_NUM_MASTERS 6 /* 5 prior to C620/Lewisburg PCH */
+struct ich_desc_master {
+ union {
+ uint32_t FLMSTRs[MAX_NUM_MASTERS]; /* Flash Masters */
+ /* For pre-Skylake platforms */
+ struct {
+ uint32_t BIOS_req_ID :16,
+ BIOS_descr_r :1,
+ BIOS_BIOS_r :1,
+ BIOS_ME_r :1,
+ BIOS_GbE_r :1,
+ BIOS_plat_r :1,
+ :3,
+ BIOS_descr_w :1,
+ BIOS_BIOS_w :1,
+ BIOS_ME_w :1,
+ BIOS_GbE_w :1,
+ BIOS_plat_w :1,
+ :3;
+ uint32_t ME_req_ID :16,
+ ME_descr_r :1,
+ ME_BIOS_r :1,
+ ME_ME_r :1,
+ ME_GbE_r :1,
+ ME_plat_r :1,
+ :3,
+ ME_descr_w :1,
+ ME_BIOS_w :1,
+ ME_ME_w :1,
+ ME_GbE_w :1,
+ ME_plat_w :1,
+ :3;
+ uint32_t GbE_req_ID :16,
+ GbE_descr_r :1,
+ GbE_BIOS_r :1,
+ GbE_ME_r :1,
+ GbE_GbE_r :1,
+ GbE_plat_r :1,
+ :3,
+ GbE_descr_w :1,
+ GbE_BIOS_w :1,
+ GbE_ME_w :1,
+ GbE_GbE_w :1,
+ GbE_plat_w :1,
+ :3;
+ };
+ /* From Skylake on */
+ struct {
+ uint32_t ext_read :4,
+ ext_write :4,
+ read :12,
+ write :12;
+ } mstr[MAX_NUM_MASTERS];
+ };
+};
+
+struct ich_desc_north_strap {
+ union {
+ uint32_t STRPs[1]; /* current maximum: ich8 */
+ struct { /* ich8 */
+ struct { /* STRP2 (in the datasheet) */
+ uint32_t MDB :1,
+ :31;
+ };
+ } ich8;
+ };
+};
+
+struct ich_desc_south_strap {
+ union {
+ uint32_t STRPs[23]; /* current maximum: gemini lake */
+ struct { /* ich8 */
+ struct { /* STRP1 */
+ uint32_t ME_DISABLE :1,
+ :6,
+ TCOMODE :1,
+ ASD :7,
+ BMCMODE :1,
+ :3,
+ GLAN_PCIE_SEL :1,
+ GPIO12_SEL :2,
+ SPICS1_LANPHYPC_SEL :1,
+ MESM2SEL :1,
+ :1,
+ ASD2 :7;
+ };
+ } ich8;
+ struct { /* ibex peak */
+ struct { /* STRP0 */
+ uint32_t :1,
+ cs_ss2 :1,
+ :5,
+ SMB_EN :1,
+ SML0_EN :1,
+ SML1_EN :1,
+ SML1FRQ :2,
+ SMB0FRQ :2,
+ SML0FRQ :2,
+ :4,
+ LANPHYPC_GP12_SEL :1,
+ cs_ss1 :1,
+ :2,
+ DMI_REQID_DIS :1,
+ :4,
+ BBBS :2,
+ :1;
+ };
+ struct { /* STRP1 */
+ uint32_t cs_ss3 :4,
+ :28;
+ };
+ struct { /* STRP2 */
+ uint32_t :8,
+ MESMASDEN :1,
+ MESMASDA :7,
+ :8,
+ MESMI2CEN :1,
+ MESMI2CA :7;
+ };
+ struct { /* STRP3 */
+ uint32_t :32;
+ };
+ struct { /* STRP4 */
+ uint32_t PHYCON :2,
+ :6,
+ GBEMAC_SMBUS_ADDR_EN :1,
+ GBEMAC_SMBUS_ADDR :7,
+ :1,
+ GBEPHY_SMBUS_ADDR :7,
+ :8;
+ };
+ struct { /* STRP5 */
+ uint32_t :32;
+ };
+ struct { /* STRP6 */
+ uint32_t :32;
+ };
+ struct { /* STRP7 */
+ uint32_t MESMA2UDID_VENDOR :16,
+ MESMA2UDID_DEVICE :16;
+ };
+ struct { /* STRP8 */
+ uint32_t :32;
+ };
+ struct { /* STRP9 */
+ uint32_t PCIEPCS1 :2,
+ PCIEPCS2 :2,
+ PCIELR1 :1,
+ PCIELR2 :1,
+ DMILR :1,
+ :1,
+ PHY_PCIEPORTSEL :3,
+ PHY_PCIE_EN :1,
+ :20;
+ };
+ struct { /* STRP10 */
+ uint32_t :1,
+ ME_BOOT_FLASH :1,
+ cs_ss5 :1,
+ VE_EN :1,
+ :4,
+ MMDDE :1,
+ MMADDR :7,
+ cs_ss7 :1,
+ :1,
+ ICC_SEL :3,
+ MER_CL1 :1,
+ :10;
+ };
+ struct { /* STRP11 */
+ uint32_t SML1GPAEN :1,
+ SML1GPA :7,
+ :16,
+ SML1I2CAEN :1,
+ SML1I2CA :7;
+ };
+ struct { /* STRP12 */
+ uint32_t :32;
+ };
+ struct { /* STRP13 */
+ uint32_t :32;
+ };
+ struct { /* STRP14 */
+ uint32_t :8,
+ VE_EN2 :1,
+ :5,
+ VE_BOOT_FLASH :1,
+ :1,
+ BW_SSD :1,
+ NVMHCI_EN :1,
+ :14;
+ };
+ struct { /* STRP15 */
+ uint32_t :3,
+ cs_ss6 :2,
+ :1,
+ IWL_EN :1,
+ :1,
+ t209min :2,
+ :22;
+ };
+ } ibex;
+ struct { /* cougar point */
+ struct { /* STRP0 */
+ uint32_t :1,
+ cs_ss1 :1,
+ :5,
+ SMB_EN :1,
+ SML0_EN :1,
+ SML1_EN :1,
+ SML1FRQ :2,
+ SMB0FRQ :2,
+ SML0FRQ :2,
+ :4,
+ LANPHYPC_GP12_SEL :1,
+ LINKSEC_DIS :1,
+ :2,
+ DMI_REQID_DIS :1,
+ :4,
+ BBBS :2,
+ :1;
+ };
+ struct { /* STRP1 */
+ uint32_t cs_ss3 :4,
+ :4,
+ cs_ss2 :1,
+ :28;
+ };
+ struct { /* STRP2 */
+ uint32_t :8,
+ MESMASDEN :1,
+ MESMASDA :7,
+ MESMMCTPAEN :1,
+ MESMMCTPA :7,
+ MESMI2CEN :1,
+ MESMI2CA :7;
+ };
+ struct { /* STRP3 */
+ uint32_t :32;
+ };
+ struct { /* STRP4 */
+ uint32_t PHYCON :2,
+ :6,
+ GBEMAC_SMBUS_ADDR_EN :1,
+ GBEMAC_SMBUS_ADDR :7,
+ :1,
+ GBEPHY_SMBUS_ADDR :7,
+ :8;
+ };
+ struct { /* STRP5 */
+ uint32_t :32;
+ };
+ struct { /* STRP6 */
+ uint32_t :32;
+ };
+ struct { /* STRP7 */
+ uint32_t MESMA2UDID_VENDOR :16,
+ MESMA2UDID_DEVICE :16;
+ };
+ struct { /* STRP8 */
+ uint32_t :32;
+ };
+ struct { /* STRP9 */
+ uint32_t PCIEPCS1 :2,
+ PCIEPCS2 :2,
+ PCIELR1 :1,
+ PCIELR2 :1,
+ DMILR :1,
+ cs_ss4 :1,
+ PHY_PCIEPORTSEL :3,
+ PHY_PCIE_EN :1,
+ :2,
+ SUB_DECODE_EN :1,
+ :7,
+ PCHHOT_SML1ALERT_SEL :1,
+ :9;
+ };
+ struct { /* STRP10 */
+ uint32_t :1,
+ ME_BOOT_FLASH :1,
+ :6,
+ MDSMBE_EN :1,
+ MDSMBE_ADD :7,
+ :2,
+ ICC_SEL :3,
+ MER_CL1 :1,
+ ICC_PRO_SEL :1,
+ Deep_SX_EN :1,
+ ME_DBG_LAN :1,
+ :7;
+ };
+ struct { /* STRP11 */
+ uint32_t SML1GPAEN :1,
+ SML1GPA :7,
+ :16,
+ SML1I2CAEN :1,
+ SML1I2CA :7;
+ };
+ struct { /* STRP12 */
+ uint32_t :32;
+ };
+ struct { /* STRP13 */
+ uint32_t :32;
+ };
+ struct { /* STRP14 */
+ uint32_t :32;
+ };
+ struct { /* STRP15 */
+ uint32_t cs_ss6 :6,
+ IWL_EN :1,
+ cs_ss5 :2,
+ :4,
+ SMLINK1_THERM_SEL :1,
+ SLP_LAN_GP29_SEL :1,
+ :16;
+ };
+ struct { /* STRP16 */
+ uint32_t :32;
+ };
+ struct { /* STRP17 */
+ uint32_t ICML :1,
+ cs_ss7 :1,
+ :30;
+ };
+ } cougar;
+ };
+};
+
+struct ich_desc_upper_map {
+ union {
+ uint32_t FLUMAP1; /* Flash Upper Map 1 */
+ struct {
+ uint32_t VTBA :8, /* ME VSCC Table Base Address */
+ VTL :8, /* ME VSCC Table Length */
+ :8,
+ MDTBA :8; /* MIP Descr. Table Base Addr. (new since Cannon Point/300) */
+ };
+ };
+ struct {
+ union { /* JEDEC-ID Register */
+ uint32_t JID;
+ struct {
+ uint32_t vid :8, /* Vendor ID */
+ cid0 :8, /* Component ID 0 */
+ cid1 :8, /* Component ID 1 */
+ :8;
+ };
+ };
+ union { /* Vendor Specific Component Capabilities */
+ uint32_t VSCC;
+ struct {
+ uint32_t ubes :2, /* Upper Block/Sector Erase Size */
+ uwg :1, /* Upper Write Granularity */
+ uwsr :1, /* Upper Write Status Required */
+ uwews :1, /* Upper Write Enable on Write Status */
+ :3,
+ ueo :8, /* Upper Erase Opcode */
+ lbes :2, /* Lower Block/Sector Erase Size */
+ lwg :1, /* Lower Write Granularity */
+ lwsr :1, /* Lower Write Status Required */
+ lwews :1, /* Lower Write Enable on Write Status */
+ :3,
+ leo :16; /* Lower Erase Opcode */
+ };
+ };
+ } vscc_table[128];
+};
+
+struct ich_descriptors {
+ struct ich_desc_content content;
+ struct ich_desc_component component;
+ struct ich_desc_region region;
+ struct ich_desc_master master;
+ struct ich_desc_north_strap north;
+ struct ich_desc_south_strap south;
+ struct ich_desc_upper_map upper;
+};
+
+ssize_t ich_number_of_regions(enum ich_chipset cs, const struct ich_desc_content *content);
+ssize_t ich_number_of_masters(enum ich_chipset cs, const struct ich_desc_content *content);
+
+void prettyprint_ich_chipset(enum ich_chipset cs);
+void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc);
+
+void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *content);
+void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc);
+void prettyprint_ich_descriptor_region(enum ich_chipset cs, const struct ich_descriptors *desc);
+void prettyprint_ich_descriptor_master(enum ich_chipset cs, const struct ich_descriptors *desc);
+
+void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap);
+void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc);
+int read_ich_descriptors_from_dump(const uint32_t *dump, size_t len, enum ich_chipset *cs, struct ich_descriptors *desc);
+
+int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc);
+int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx);
+
+int layout_from_ich_descriptors(struct flashrom_layout **, const void *dump, size_t len);
+
+#endif /* __ICH_DESCRIPTORS_H__ */
diff --git a/include/layout.h b/include/layout.h
new file mode 100644
index 000000000..5614beaf8
--- /dev/null
+++ b/include/layout.h
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2005-2008 coresystems GmbH
+ * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
+ * Copyright (C) 2011-2013 Stefan Tauner
+ * Copyright (C) 2016 secunet Security Networks AG
+ * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LAYOUT_H__
+#define __LAYOUT_H__ 1
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Types and macros regarding the maximum flash space size supported by generic code. */
+typedef uint32_t chipoff_t; /* Able to store any addressable offset within a supported flash memory. */
+typedef uint32_t chipsize_t; /* Able to store the number of bytes of any supported flash memory. */
+#define FL_MAX_CHIPOFF_BITS (24)
+#define FL_MAX_CHIPOFF ((chipoff_t)(1ULL<<FL_MAX_CHIPOFF_BITS)-1)
+#define PRIxCHIPOFF "06"PRIx32
+#define PRIuCHIPSIZE PRIu32
+
+#define MAX_ROMLAYOUT 128
+
+struct flash_region {
+ char *name;
+ chipoff_t start;
+ chipoff_t end;
+ bool read_prot;
+ bool write_prot;
+};
+
+struct romentry {
+ struct romentry *next;
+
+ bool included;
+ char *file;
+
+ struct flash_region region;
+};
+
+struct flashrom_layout;
+
+struct layout_include_args;
+
+struct flashrom_flashctx;
+const struct flashrom_layout *get_default_layout(const struct flashrom_flashctx *);
+const struct flashrom_layout *get_layout(const struct flashrom_flashctx *);
+
+int layout_from_file(struct flashrom_layout **, const char *name);
+
+int register_include_arg(struct layout_include_args **, const char *arg);
+int process_include_args(struct flashrom_layout *, const struct layout_include_args *);
+void cleanup_include_args(struct layout_include_args **);
+
+const struct romentry *layout_next_included_region(const struct flashrom_layout *, chipoff_t);
+const struct romentry *layout_next_included(const struct flashrom_layout *, const struct romentry *);
+const struct romentry *layout_next(const struct flashrom_layout *, const struct romentry *);
+int included_regions_overlap(const struct flashrom_layout *);
+void prepare_layout_for_extraction(struct flashrom_flashctx *);
+int layout_sanity_checks(const struct flashrom_flashctx *);
+int check_for_unwritable_regions(const struct flashrom_flashctx *flash, unsigned int start, unsigned int len);
+void get_flash_region(const struct flashrom_flashctx *flash, int addr, struct flash_region *region);
+
+#endif /* !__LAYOUT_H__ */
diff --git a/include/libflashrom.h b/include/libflashrom.h
new file mode 100644
index 000000000..e87776be1
--- /dev/null
+++ b/include/libflashrom.h
@@ -0,0 +1,598 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Google Inc.
+ * Copyright (C) 2012 secunet Security Networks AG
+ * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LIBFLASHROM_H__
+#define __LIBFLASHROM_H__ 1
+
+/**
+ * @mainpage
+ *
+ * Have a look at the Modules section for a function reference.
+ */
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+/**
+ * @defgroup flashrom-general General
+ * @{
+ */
+
+/**
+ * @brief Initialize libflashrom.
+ *
+ * @param perform_selfcheck If not zero, perform a self check.
+ * @return 0 on success
+ */
+int flashrom_init(int perform_selfcheck);
+/**
+ * @brief Shut down libflashrom.
+ * @return 0 on success
+ */
+int flashrom_shutdown(void);
+enum flashrom_log_level {
+ FLASHROM_MSG_ERROR = 0,
+ FLASHROM_MSG_WARN = 1,
+ FLASHROM_MSG_INFO = 2,
+ FLASHROM_MSG_DEBUG = 3,
+ FLASHROM_MSG_DEBUG2 = 4,
+ FLASHROM_MSG_SPEW = 5,
+};
+typedef int(flashrom_log_callback)(enum flashrom_log_level, const char *format, va_list);
+/**
+ * @brief Set the log callback function.
+ *
+ * Set a callback function which will be invoked whenever libflashrom wants
+ * to output messages. This allows frontends to do whatever they see fit with
+ * such messages, e.g. write them to syslog, or to a file, or print them in a
+ * GUI window, etc.
+ *
+ * @param log_callback Pointer to the new log callback function.
+ */
+void flashrom_set_log_callback(flashrom_log_callback *log_callback);
+
+enum flashrom_progress_stage {
+ FLASHROM_PROGRESS_READ,
+ FLASHROM_PROGRESS_WRITE,
+ FLASHROM_PROGRESS_ERASE,
+ FLASHROM_PROGRESS_NR,
+};
+struct flashrom_progress {
+ enum flashrom_progress_stage stage;
+ size_t current;
+ size_t total;
+ void *user_data;
+};
+struct flashrom_flashctx;
+typedef void(flashrom_progress_callback)(struct flashrom_flashctx *flashctx);
+/**
+ * @brief Set the progress callback function.
+ *
+ * Set a callback function which will be invoked whenever libflashrom wants
+ * to indicate the progress has changed. This allows frontends to do whatever
+ * they see fit with such values, e.g. update a progress bar in a GUI tool.
+ *
+ * @param progress_callback Pointer to the new progress callback function.
+ * @param progress_state Pointer to progress state to include with the progress
+ * callback.
+ */
+void flashrom_set_progress_callback(struct flashrom_flashctx *const flashctx,
+ flashrom_progress_callback *progress_callback, struct flashrom_progress *progress_state);
+
+/** @} */ /* end flashrom-general */
+
+/**
+ * @defgroup flashrom-query Querying
+ * @{
+ */
+
+enum flashrom_test_state {
+ FLASHROM_TESTED_OK = 0,
+ FLASHROM_TESTED_NT = 1,
+ FLASHROM_TESTED_BAD = 2,
+ FLASHROM_TESTED_DEP = 3,
+ FLASHROM_TESTED_NA = 4,
+};
+
+struct flashrom_flashchip_info {
+ const char *vendor;
+ const char *name;
+ unsigned int total_size;
+ struct flashrom_tested {
+ enum flashrom_test_state probe;
+ enum flashrom_test_state read;
+ enum flashrom_test_state erase;
+ enum flashrom_test_state write;
+ enum flashrom_test_state wp;
+ } tested;
+};
+
+struct flashrom_board_info {
+ const char *vendor;
+ const char *name;
+ enum flashrom_test_state working;
+};
+
+struct flashrom_chipset_info {
+ const char *vendor;
+ const char *chipset;
+ uint16_t vendor_id;
+ uint16_t chipset_id;
+ enum flashrom_test_state status;
+};
+
+/**
+ * @brief Returns flashrom version
+ * @return flashrom version
+ */
+const char *flashrom_version_info(void);
+/**
+ * @brief Returns list of supported flash chips
+ * @return List of supported flash chips, or NULL if an error occurred
+ */
+struct flashrom_flashchip_info *flashrom_supported_flash_chips(void);
+/**
+ * @brief Returns list of supported mainboards
+ * @return List of supported mainboards, or NULL if an error occurred
+ */
+struct flashrom_board_info *flashrom_supported_boards(void);
+/**
+ * @brief Returns list of supported chipsets
+ * @return List of supported chipsets, or NULL if an error occurred
+ */
+struct flashrom_chipset_info *flashrom_supported_chipsets(void);
+/**
+ * @brief Frees memory allocated by libflashrom API
+ * @param p Pointer to block of memory which should be freed
+ * @return 0 on success
+ */
+int flashrom_data_free(void *const p);
+
+/** @} */ /* end flashrom-query */
+
+/**
+ * @defgroup flashrom-prog Programmers
+ * @{
+ */
+struct flashrom_programmer;
+
+/**
+ * @brief Initialize the specified programmer.
+ *
+ * Currently, only one programmer may be initialized at a time.
+ *
+ * @param[out] flashprog Points to a pointer of type struct flashrom_programmer
+ * that will be set if programmer initialization succeeds.
+ * *flashprog has to be shutdown by the caller with @ref
+ * flashrom_programmer_shutdown.
+ * @param[in] prog_name Name of the programmer to initialize.
+ * @param[in] prog_params Pointer to programmer specific parameters.
+ * @return 0 on success
+ */
+int flashrom_programmer_init(struct flashrom_programmer **flashprog, const char *prog_name, const char *prog_params);
+/**
+ * @brief Shut down the initialized programmer.
+ *
+ * @param flashprog The programmer to shut down.
+ * @return 0 on success
+ */
+int flashrom_programmer_shutdown(struct flashrom_programmer *flashprog);
+
+/** @} */ /* end flashrom-prog */
+
+/**
+ * @defgroup flashrom-flash Flash chips
+ * @{
+ */
+
+/**
+ * @brief Probe for a flash chip.
+ *
+ * Probes for a flash chip and returns a flash context, that can be used
+ * later with flash chip and @ref flashrom-ops "image operations", if
+ * exactly one matching chip is found.
+ *
+ * @param[out] flashctx Points to a pointer of type struct flashrom_flashctx
+ * that will be set if exactly one chip is found. *flashctx
+ * has to be freed by the caller with @ref flashrom_flash_release.
+ * @param[in] flashprog The flash programmer used to access the chip.
+ * @param[in] chip_name Name of a chip to probe for, or NULL to probe for
+ * all known chips.
+ * @return 0 on success,
+ * 3 if multiple chips were found,
+ * 2 if no chip was found,
+ * or 1 on any other error.
+ */
+int flashrom_flash_probe(struct flashrom_flashctx **flashctx, const struct flashrom_programmer *flashprog, const char *chip_name);
+/**
+ * @brief Returns the size of the specified flash chip in bytes.
+ *
+ * @param flashctx The queried flash context.
+ * @return Size of flash chip in bytes.
+ */
+size_t flashrom_flash_getsize(const struct flashrom_flashctx *flashctx);
+/**
+ * @brief Erase the specified ROM chip.
+ *
+ * If a layout is set in the given flash context, only included regions
+ * will be erased.
+ *
+ * @param flashctx The context of the flash chip to erase.
+ * @return 0 on success.
+ */
+int flashrom_flash_erase(struct flashrom_flashctx *flashctx);
+/**
+ * @brief Free a flash context.
+ *
+ * @param flashctx Flash context to free.
+ */
+void flashrom_flash_release(struct flashrom_flashctx *flashctx);
+
+enum flashrom_flag {
+ FLASHROM_FLAG_FORCE,
+ FLASHROM_FLAG_FORCE_BOARDMISMATCH,
+ FLASHROM_FLAG_VERIFY_AFTER_WRITE,
+ FLASHROM_FLAG_VERIFY_WHOLE_CHIP,
+ FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS,
+ FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS,
+};
+
+/**
+ * @brief Set a flag in the given flash context.
+ *
+ * @param flashctx Flash context to alter.
+ * @param flag Flag that is to be set / cleared.
+ * @param value Value to set.
+ */
+void flashrom_flag_set(struct flashrom_flashctx *flashctx, enum flashrom_flag flag, bool value);
+/**
+ * @brief Return the current value of a flag in the given flash context.
+ *
+ * @param flashctx Flash context to read from.
+ * @param flag Flag to be read.
+ * @return Current value of the flag.
+ */
+bool flashrom_flag_get(const struct flashrom_flashctx *flashctx, enum flashrom_flag flag);
+
+/** @} */ /* end flashrom-flash */
+
+/**
+ * @defgroup flashrom-ops Operations
+ * @{
+ */
+
+/**
+ * @brief Read the current image from the specified ROM chip.
+ *
+ * If a layout is set in the specified flash context, only included regions
+ * will be read.
+ *
+ * @param flashctx The context of the flash chip.
+ * @param buffer Target buffer to write image to.
+ * @param buffer_len Size of target buffer in bytes.
+ * @return 0 on success,
+ * 2 if buffer_len is too small for the flash chip's contents,
+ * or 1 on any other failure.
+ */
+int flashrom_image_read(struct flashrom_flashctx *flashctx, void *buffer, size_t buffer_len);
+/**
+ * @brief Write the specified image to the ROM chip.
+ *
+ * If a layout is set in the specified flash context, only erase blocks
+ * containing included regions will be touched.
+ *
+ * @param flashctx The context of the flash chip.
+ * @param buffer Source buffer to read image from (may be altered for full verification).
+ * @param buffer_len Size of source buffer in bytes.
+ * @param refbuffer If given, assume flash chip contains same data as `refbuffer`.
+ * @return 0 on success,
+ * 4 if buffer_len doesn't match the size of the flash chip,
+ * 3 if write was tried but nothing has changed,
+ * 2 if write failed and flash contents changed,
+ * or 1 on any other failure.
+ */
+int flashrom_image_write(struct flashrom_flashctx *flashctx, void *buffer, size_t buffer_len, const void *refbuffer);
+/**
+ * @brief Verify the ROM chip's contents with the specified image.
+ *
+ * If a layout is set in the specified flash context, only included regions
+ * will be verified.
+ *
+ * @param flashctx The context of the flash chip.
+ * @param buffer Source buffer to verify with.
+ * @param buffer_len Size of source buffer in bytes.
+ * @return 0 on success,
+ * 3 if the chip's contents don't match,
+ * 2 if buffer_len doesn't match the size of the flash chip,
+ * or 1 on any other failure.
+ */
+int flashrom_image_verify(struct flashrom_flashctx *flashctx, const void *buffer, size_t buffer_len);
+
+/** @} */ /* end flashrom-ops */
+
+/**
+ * @defgroup flashrom-layout Layout handling
+ * @{
+ */
+
+struct flashrom_layout;
+/**
+ * @brief Create a new, empty layout.
+ *
+ * @param layout Pointer to returned layout reference.
+ *
+ * @return 0 on success,
+ * 1 if out of memory.
+ */
+int flashrom_layout_new(struct flashrom_layout **layout);
+
+/**
+ * @brief Read a layout from the Intel ICH descriptor in the flash.
+ *
+ * Optionally verify that the layout matches the one in the given
+ * descriptor dump.
+ *
+ * @param[out] layout Points to a struct flashrom_layout pointer that
+ * gets set if the descriptor is read and parsed
+ * successfully.
+ * @param[in] flashctx Flash context to read the descriptor from flash.
+ * @param[in] dump The descriptor dump to compare to or NULL.
+ * @param[in] len The length of the descriptor dump.
+ *
+ * @return 0 on success,
+ * 6 if descriptor parsing isn't implemented for the host,
+ * 5 if the descriptors don't match,
+ * 4 if the descriptor dump couldn't be parsed,
+ * 3 if the descriptor on flash couldn't be parsed,
+ * 2 if the descriptor on flash couldn't be read,
+ * 1 on any other error.
+ */
+int flashrom_layout_read_from_ifd(struct flashrom_layout **layout, struct flashrom_flashctx *flashctx, const void *dump, size_t len);
+/**
+ * @brief Read a layout by searching the flash chip for fmap.
+ *
+ * @param[out] layout Points to a struct flashrom_layout pointer that
+ * gets set if the fmap is read and parsed successfully.
+ * @param[in] flashctx Flash context
+ * @param[in] offset Offset to begin searching for fmap.
+ * @param[in] length Length of address space to search.
+ *
+ * @return 0 on success,
+ * 3 if fmap parsing isn't implemented for the host,
+ * 2 if the fmap couldn't be read,
+ * 1 on any other error.
+ */
+int flashrom_layout_read_fmap_from_rom(struct flashrom_layout **layout,
+ struct flashrom_flashctx *flashctx, size_t offset, size_t length);
+/**
+ * @brief Read a layout by searching a buffer for fmap.
+ *
+ * @param[out] layout Points to a struct flashrom_layout pointer that
+ * gets set if the fmap is read and parsed successfully.
+ * @param[in] flashctx Flash context
+ * @param[in] buffer Buffer to search in
+ * @param[in] len Size of buffer to search
+ *
+ * @return 0 on success,
+ * 3 if fmap parsing isn't implemented for the host,
+ * 2 if the fmap couldn't be read,
+ * 1 on any other error.
+ */
+int flashrom_layout_read_fmap_from_buffer(struct flashrom_layout **layout,
+ struct flashrom_flashctx *flashctx, const uint8_t *buffer, size_t len);
+/**
+ * @brief Add a region to an existing layout.
+ *
+ * @param layout The existing layout.
+ * @param start Start address of the region.
+ * @param end End address (inclusive) of the region.
+ * @param name Name of the region.
+ *
+ * @return 0 on success,
+ * 1 if out of memory.
+ */
+int flashrom_layout_add_region(struct flashrom_layout *layout, size_t start, size_t end, const char *name);
+/**
+ * @brief Mark given region as included.
+ *
+ * @param layout The layout to alter.
+ * @param name The name of the region to include.
+ *
+ * @return 0 on success,
+ * 1 if the given name can't be found.
+ */
+int flashrom_layout_include_region(struct flashrom_layout *layout, const char *name);
+/**
+ * @brief Mark given region as not included.
+ *
+ * @param layout The layout to alter.
+ * @param name The name of the region to exclude.
+ *
+ * @return 0 on success,
+ * 1 if the given name can't be found.
+ */
+int flashrom_layout_exclude_region(struct flashrom_layout *layout, const char *name);
+/**
+ * @brief Get given region's offset and length.
+ *
+ * @param[in] layout The existing layout.
+ * @param[in] name The name of the region.
+ * @param[out] start The start address to be written.
+ * @param[out] len The length of the region to be written.
+ *
+ * @return 0 on success,
+ * 1 if the given name can't be found.
+ */
+int flashrom_layout_get_region_range(struct flashrom_layout *layout, const char *name,
+ unsigned int *start, unsigned int *len);
+/**
+ * @brief Free a layout.
+ *
+ * @param layout Layout to free.
+ */
+void flashrom_layout_release(struct flashrom_layout *layout);
+/**
+ * @brief Set the active layout for a flash context.
+ *
+ * Note: The caller must not release the layout as long as it is used through
+ * the given flash context.
+ *
+ * @param flashctx Flash context whose layout will be set.
+ * @param layout Layout to bet set.
+ */
+void flashrom_layout_set(struct flashrom_flashctx *flashctx, const struct flashrom_layout *layout);
+
+/** @} */ /* end flashrom-layout */
+
+/**
+ * @defgroup flashrom-wp Write Protect
+ * @{
+ */
+
+enum flashrom_wp_result {
+ FLASHROM_WP_OK = 0,
+ FLASHROM_WP_ERR_CHIP_UNSUPPORTED = 1,
+ FLASHROM_WP_ERR_OTHER = 2,
+ FLASHROM_WP_ERR_READ_FAILED = 3,
+ FLASHROM_WP_ERR_WRITE_FAILED = 4,
+ FLASHROM_WP_ERR_VERIFY_FAILED = 5,
+ FLASHROM_WP_ERR_RANGE_UNSUPPORTED = 6,
+ FLASHROM_WP_ERR_MODE_UNSUPPORTED = 7,
+ FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE = 8,
+ FLASHROM_WP_ERR_UNSUPPORTED_STATE = 9
+};
+
+enum flashrom_wp_mode {
+ FLASHROM_WP_MODE_DISABLED,
+ FLASHROM_WP_MODE_HARDWARE,
+ FLASHROM_WP_MODE_POWER_CYCLE,
+ FLASHROM_WP_MODE_PERMANENT
+};
+struct flashrom_wp_cfg;
+struct flashrom_wp_ranges;
+/**
+ * @brief Create a new empty WP configuration.
+ *
+ * @param[out] cfg Points to a pointer of type struct flashrom_wp_cfg that will
+ * be set if creation succeeds. *cfg has to be freed by the
+ * caller with @ref flashrom_wp_cfg_release.
+ * @return 0 on success
+ * >0 on failure
+ */
+enum flashrom_wp_result flashrom_wp_cfg_new(struct flashrom_wp_cfg **cfg);
+/**
+ * @brief Free a WP configuration.
+ *
+ * @param[in] cfg Pointer to the flashrom_wp_cfg to free.
+ */
+void flashrom_wp_cfg_release(struct flashrom_wp_cfg *cfg);
+/**
+ * @brief Set the protection mode for a WP configuration.
+ *
+ * @param[in] mode The protection mode to set.
+ * @param[out] cfg Pointer to the flashrom_wp_cfg structure to modify.
+ */
+void flashrom_wp_set_mode(struct flashrom_wp_cfg *cfg, enum flashrom_wp_mode mode);
+/**
+ * @brief Get the protection mode from a WP configuration.
+ *
+ * @param[in] cfg The WP configuration to get the protection mode from.
+ * @return The configuration's protection mode.
+ */
+enum flashrom_wp_mode flashrom_wp_get_mode(const struct flashrom_wp_cfg *cfg);
+/**
+ * @brief Set the protection range for a WP configuration.
+ *
+ * @param[out] cfg Pointer to the flashrom_wp_cfg structure to modify.
+ * @param[in] start The range's start address.
+ * @param[in] len The range's length.
+ */
+void flashrom_wp_set_range(struct flashrom_wp_cfg *cfg, size_t start, size_t len);
+/**
+ * @brief Get the protection range from a WP configuration.
+ *
+ * @param[out] start Points to a size_t to write the range start to.
+ * @param[out] len Points to a size_t to write the range length to.
+ * @param[in] cfg The WP configuration to get the range from.
+ */
+void flashrom_wp_get_range(size_t *start, size_t *len, const struct flashrom_wp_cfg *cfg);
+
+/**
+ * @brief Read the current WP configuration from a flash chip.
+ *
+ * @param[out] cfg Pointer to a struct flashrom_wp_cfg to store the chip's
+ * configuration in.
+ * @param[in] flash The flash context used to access the chip.
+ * @return 0 on success
+ * >0 on failure
+ */
+enum flashrom_wp_result flashrom_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashrom_flashctx *flash);
+/**
+ * @brief Write a WP configuration to a flash chip.
+ *
+ * @param[in] flash The flash context used to access the chip.
+ * @param[in] cfg The WP configuration to write to the chip.
+ * @return 0 on success
+ * >0 on failure
+ */
+enum flashrom_wp_result flashrom_wp_write_cfg(struct flashrom_flashctx *flash, const struct flashrom_wp_cfg *cfg);
+
+/**
+ * @brief Get a list of protection ranges supported by the flash chip.
+ *
+ * @param[out] ranges Points to a pointer of type struct flashrom_wp_ranges
+ * that will be set if available ranges are found. Finding
+ * available ranges may not always be possible, even if the
+ * chip's protection range can be read or modified. *ranges
+ * must be freed using @ref flashrom_wp_ranges_release.
+ * @param[in] flash The flash context used to access the chip.
+ * @return 0 on success
+ * >0 on failure
+ */
+enum flashrom_wp_result flashrom_wp_get_available_ranges(struct flashrom_wp_ranges **ranges, struct flashrom_flashctx *flash);
+/**
+ * @brief Get a number of protection ranges in a range list.
+ *
+ * @param[in] ranges The range list to get the count from.
+ * @return Number of ranges in the list.
+ */
+size_t flashrom_wp_ranges_get_count(const struct flashrom_wp_ranges *ranges);
+/**
+ * @brief Get a protection range from a range list.
+ *
+ * @param[out] start Points to a size_t to write the range's start to.
+ * @param[out] len Points to a size_t to write the range's length to.
+ * @param[in] ranges The range list to get the range from.
+ * @param[in] index Index of the range to get.
+ * @return 0 on success
+ * >0 on failure
+ */
+enum flashrom_wp_result flashrom_wp_ranges_get_range(size_t *start, size_t *len, const struct flashrom_wp_ranges *ranges, unsigned int index);
+/**
+ * @brief Free a WP range list.
+ *
+ * @param[out] ranges Pointer to the flashrom_wp_ranges to free.
+ */
+void flashrom_wp_ranges_release(struct flashrom_wp_ranges *ranges);
+
+/** @} */ /* end flashrom-wp */
+
+#endif /* !__LIBFLASHROM_H__ */
diff --git a/include/platform.h b/include/platform.h
new file mode 100644
index 000000000..3cde2edae
--- /dev/null
+++ b/include/platform.h
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2022 secunet Security Networks AG
+ * (written by Thomas Heijligen <thomas.heijligen@secunet.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Header file for platform abstraction.
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__ 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* convert cpu native endian to little endian */
+uint8_t cpu_to_le8 (uint8_t value);
+uint16_t cpu_to_le16(uint16_t value);
+uint32_t cpu_to_le32(uint32_t value);
+uint64_t cpu_to_le64(uint64_t value);
+
+/* convert cpu native endian to big endian */
+uint8_t cpu_to_be8 (uint8_t value);
+uint16_t cpu_to_be16(uint16_t value);
+uint32_t cpu_to_be32(uint32_t value);
+uint64_t cpu_to_be64(uint64_t value);
+
+/* convert little endian to cpu native endian */
+uint8_t le_to_cpu8 (uint8_t value);
+uint16_t le_to_cpu16(uint16_t value);
+uint32_t le_to_cpu32(uint32_t value);
+uint64_t le_to_cpu64(uint64_t value);
+
+/* convert big endian to cpu native endian */
+uint8_t be_to_cpu8 (uint8_t value);
+uint16_t be_to_cpu16(uint16_t value);
+uint32_t be_to_cpu32(uint32_t value);
+uint64_t be_to_cpu64(uint64_t value);
+
+/* read value from base at offset in little endian */
+uint8_t read_le8 (const void *base, size_t offset);
+uint16_t read_le16(const void *base, size_t offset);
+uint32_t read_le32(const void *base, size_t offset);
+uint64_t read_le64(const void *base, size_t offset);
+
+/* read value from base at offset in big endian */
+uint8_t read_be8 (const void *base, size_t offset);
+uint16_t read_be16(const void *base, size_t offset);
+uint32_t read_be32(const void *base, size_t offset);
+uint64_t read_be64(const void *base, size_t offset);
+
+#endif /* !__PLATFORM_H__ */
diff --git a/include/platform/pci.h b/include/platform/pci.h
new file mode 100644
index 000000000..4ac108f26
--- /dev/null
+++ b/include/platform/pci.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2022 secunet Security Networks AG
+ * (written by Thomas Heijligen <thomas.heijligen@secunet.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PLATFORM_PCI_H__
+#define __PLATFORM_PCI_H__
+
+/* Some NetBSDs are using an other include path for pci.h
+ * e.g. NetBSD 9.0 on sparc64 pciutils-3.7.0nb2.
+ * Other NetBSD platforms and versions uses the default path under pci/pci.h
+ */
+#if __has_include(<pciutils/pci.h>)
+#include <pciutils/pci.h>
+#else
+#include <pci/pci.h>
+#endif
+
+#endif /* __PLATFORM_PCI_H__ */
diff --git a/include/platform/swap.h b/include/platform/swap.h
new file mode 100644
index 000000000..12f310654
--- /dev/null
+++ b/include/platform/swap.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2022 secunet Security Networks AG
+ * (written by Thomas Heijligen <thomas.heijligen@secunet.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * inline functions and macros shared by endian conversion functions
+ */
+
+#ifndef ___SWAP_H___
+#define ___SWAP_H___ 1
+
+#include <stdint.h>
+
+/* swap bytes */
+/* OpenBSD has conflicting definitions for swapX, _swap_X and __swapX */
+static inline uint8_t ___swap8(const uint8_t value)
+{
+ return (value & (uint8_t)0xffU);
+}
+
+static inline uint16_t ___swap16(const uint16_t value)
+{
+ return ((value & (uint16_t)0x00ffU) << 8) |
+ ((value & (uint16_t)0xff00U) >> 8);
+}
+
+static inline uint32_t ___swap32(const uint32_t value)
+{
+ return ((value & (uint32_t)0x000000ffUL) << 24) |
+ ((value & (uint32_t)0x0000ff00UL) << 8) |
+ ((value & (uint32_t)0x00ff0000UL) >> 8) |
+ ((value & (uint32_t)0xff000000UL) >> 24);
+}
+
+static inline uint64_t ___swap64(const uint64_t value)
+{
+ return ((value & (uint64_t)0x00000000000000ffULL) << 56) |
+ ((value & (uint64_t)0x000000000000ff00ULL) << 40) |
+ ((value & (uint64_t)0x0000000000ff0000ULL) << 24) |
+ ((value & (uint64_t)0x00000000ff000000ULL) << 8) |
+ ((value & (uint64_t)0x000000ff00000000ULL) >> 8) |
+ ((value & (uint64_t)0x0000ff0000000000ULL) >> 24) |
+ ((value & (uint64_t)0x00ff000000000000ULL) >> 40) |
+ ((value & (uint64_t)0xff00000000000000ULL) >> 56);
+}
+
+/*
+ * macro to return the same value as passed.
+ *
+ * `___return_same(cpu_to_le, 8)`
+ * expands to
+ * `uint8_t cpu_to_le8 (const uint8_t value) { return value; }`
+ */
+#define ___return_same(name, bits) \
+ uint##bits##_t name##bits (const uint##bits##_t value) { return value; }
+
+/*
+ * macro to return the swapped value as passed.
+ *
+ * `___return_swapped(cpu_to_be, 8)`
+ * expands to
+ * `uint8_t cpu_to_be8 (const uint8_t value) { return ___swap8 (value); }`
+ */
+#define ___return_swapped(name, bits) \
+ uint##bits##_t name##bits (const uint##bits##_t value) { return ___swap##bits (value); }
+
+#endif /* !___SWAP_H___ */
diff --git a/include/programmer.h b/include/programmer.h
new file mode 100644
index 000000000..562f58ad2
--- /dev/null
+++ b/include/programmer.h
@@ -0,0 +1,538 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2000 Silicon Integrated System Corporation
+ * Copyright (C) 2000 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2005-2009 coresystems GmbH
+ * Copyright (C) 2006-2009 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PROGRAMMER_H__
+#define __PROGRAMMER_H__ 1
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "flash.h" /* for chipaddr and flashctx */
+
+enum programmer_type {
+ PCI = 1, /* to detect uninitialized values */
+ USB,
+ OTHER,
+};
+struct board_cfg;
+struct programmer_cfg {
+ char *params;
+ struct board_cfg *bcfg;
+};
+
+struct dev_entry {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ const enum test_state status;
+ const char *vendor_name;
+ const char *device_name;
+};
+
+struct programmer_entry {
+ const char *name;
+ const enum programmer_type type;
+ union {
+ const struct dev_entry *const dev;
+ const char *const note;
+ } devs;
+
+ int (*init) (const struct programmer_cfg *cfg);
+};
+
+extern const struct programmer_entry *const programmer_table[];
+extern const size_t programmer_table_size;
+
+/* programmer drivers */
+extern const struct programmer_entry programmer_asm106x;
+extern const struct programmer_entry programmer_atahpt;
+extern const struct programmer_entry programmer_atapromise;
+extern const struct programmer_entry programmer_atavia;
+extern const struct programmer_entry programmer_buspirate_spi;
+extern const struct programmer_entry programmer_ch341a_spi;
+extern const struct programmer_entry programmer_ch347_spi;
+extern const struct programmer_entry programmer_dediprog;
+extern const struct programmer_entry programmer_developerbox;
+extern const struct programmer_entry programmer_digilent_spi;
+extern const struct programmer_entry programmer_drkaiser;
+extern const struct programmer_entry programmer_dummy;
+extern const struct programmer_entry programmer_ft2232_spi;
+extern const struct programmer_entry programmer_gfxnvidia;
+extern const struct programmer_entry programmer_internal;
+extern const struct programmer_entry programmer_it8212;
+extern const struct programmer_entry programmer_jlink_spi;
+extern const struct programmer_entry programmer_linux_mtd;
+extern const struct programmer_entry programmer_linux_spi;
+extern const struct programmer_entry programmer_parade_lspcon;
+extern const struct programmer_entry programmer_mediatek_i2c_spi;
+extern const struct programmer_entry programmer_mstarddc_spi;
+extern const struct programmer_entry programmer_ni845x_spi;
+extern const struct programmer_entry programmer_nic3com;
+extern const struct programmer_entry programmer_nicintel;
+extern const struct programmer_entry programmer_nicintel_eeprom;
+extern const struct programmer_entry programmer_nicintel_spi;
+extern const struct programmer_entry programmer_nicnatsemi;
+extern const struct programmer_entry programmer_nicrealtek;
+extern const struct programmer_entry programmer_ogp_spi;
+extern const struct programmer_entry programmer_pickit2_spi;
+extern const struct programmer_entry programmer_pony_spi;
+extern const struct programmer_entry programmer_raiden_debug_spi;
+extern const struct programmer_entry programmer_rayer_spi;
+extern const struct programmer_entry programmer_realtek_mst_i2c_spi;
+extern const struct programmer_entry programmer_satamv;
+extern const struct programmer_entry programmer_satasii;
+extern const struct programmer_entry programmer_serprog;
+extern const struct programmer_entry programmer_stlinkv3_spi;
+extern const struct programmer_entry programmer_usbblaster_spi;
+extern const struct programmer_entry programmer_dirtyjtag_spi;
+
+int programmer_init(const struct programmer_entry *prog, const char *param);
+int programmer_shutdown(void);
+
+struct bitbang_spi_master {
+ /* Note that CS# is active low, so val=0 means the chip is active. */
+ void (*set_cs) (int val, void *spi_data);
+ void (*set_sck) (int val, void *spi_data);
+ void (*set_mosi) (int val, void *spi_data);
+ int (*get_miso) (void *spi_data);
+ void (*request_bus) (void *spi_data);
+ void (*release_bus) (void *spi_data);
+ /* optional functions to optimize xfers */
+ void (*set_sck_set_mosi) (int sck, int mosi, void *spi_data);
+ int (*set_sck_get_miso) (int sck, void *spi_data);
+ /* Length of half a clock period in usecs. */
+ unsigned int half_period;
+};
+
+struct pci_dev;
+struct pci_filter;
+
+/* pcidev.c */
+// FIXME: This needs to be local, not global(?)
+extern struct pci_access *pacc;
+int pci_init_common(void);
+uintptr_t pcidev_readbar(struct pci_dev *dev, int bar);
+struct pci_dev *pcidev_init(const struct programmer_cfg *cfg, const struct dev_entry *devs, int bar);
+struct pci_dev *pcidev_scandev(struct pci_filter *filter, struct pci_dev *start);
+struct pci_dev *pcidev_getdevfn(struct pci_dev *dev, const int func);
+struct pci_dev *pcidev_find_vendorclass(uint16_t vendor, uint16_t devclass);
+struct pci_dev *pcidev_card_find(uint16_t vendor, uint16_t device, uint16_t card_vendor, uint16_t card_device);
+struct pci_dev *pcidev_find(uint16_t vendor, uint16_t device);
+/* rpci_write_* are reversible writes. The original PCI config space register
+ * contents will be restored on shutdown.
+ * To clone the pci_dev instances internally, the `pacc` global
+ * variable has to reference a pci_access method that is compatible
+ * with the given pci_dev handle. The referenced pci_access (not
+ * the variable) has to stay valid until the shutdown handlers are
+ * finished.
+ */
+int rpci_write_byte(struct pci_dev *dev, int reg, uint8_t data);
+int rpci_write_word(struct pci_dev *dev, int reg, uint16_t data);
+int rpci_write_long(struct pci_dev *dev, int reg, uint32_t data);
+
+#if CONFIG_INTERNAL == 1
+struct penable {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ enum chipbustype buses;
+ const enum test_state status;
+ const char *vendor_name;
+ const char *device_name;
+ int (*doit) (const struct programmer_cfg *cfg, struct pci_dev *dev, const char *name);
+};
+
+extern const struct penable chipset_enables[];
+
+enum board_match_phase {
+ P1,
+ P2,
+ P3
+};
+
+struct board_cfg {
+ int is_laptop;
+ bool laptop_ok;
+};
+
+struct board_match {
+ /* Any device, but make it sensible, like the ISA bridge. */
+ uint16_t first_vendor;
+ uint16_t first_device;
+ uint16_t first_card_vendor;
+ uint16_t first_card_device;
+
+ /* Any device, but make it sensible, like
+ * the host bridge. May be NULL.
+ */
+ uint16_t second_vendor;
+ uint16_t second_device;
+ uint16_t second_card_vendor;
+ uint16_t second_card_device;
+
+ /* Pattern to match DMI entries. May be NULL. */
+ const char *dmi_pattern;
+
+ /* The vendor / part name from the coreboot table. May be NULL. */
+ const char *lb_vendor;
+ const char *lb_part;
+
+ enum board_match_phase phase;
+
+ const char *vendor_name;
+ const char *board_name;
+
+ int max_rom_decode_parallel;
+ const enum test_state status;
+ int (*enable) (struct board_cfg *cfg); /* May be NULL. */
+};
+
+extern const struct board_match board_matches[];
+extern const size_t board_matches_size;
+
+struct board_info {
+ const char *vendor;
+ const char *name;
+ const enum test_state working;
+#ifdef CONFIG_PRINT_WIKI
+ const char *url;
+ const char *note;
+#endif
+};
+
+extern const struct board_info boards_known[];
+extern const struct board_info laptops_known[];
+#endif
+
+/* udelay.c */
+void myusec_delay(unsigned int usecs);
+void myusec_calibrate_delay(void);
+void internal_sleep(unsigned int usecs);
+void default_delay(unsigned int usecs);
+
+#if CONFIG_INTERNAL == 1
+/* board_enable.c */
+int selfcheck_board_enables(void);
+int board_parse_parameter(const char *boardstring, char **vendor, char **model);
+void w836xx_ext_enter(uint16_t port);
+void w836xx_ext_leave(uint16_t port);
+void probe_superio_winbond(void);
+int it8705f_write_enable(uint8_t port);
+uint8_t sio_read(uint16_t port, uint8_t reg);
+void sio_write(uint16_t port, uint8_t reg, uint8_t data);
+void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask);
+void board_handle_before_superio(struct board_cfg *cfg, bool force_boardenable);
+void board_handle_before_laptop(struct board_cfg *cfg, bool force_boardenable);
+int board_flash_enable(struct board_cfg *cfg, const char *vendor, const char *model, const char *cb_vendor, const char *cb_model, bool force_boardenable);
+
+/* chipset_enable.c */
+int chipset_flash_enable(const struct programmer_cfg *cfg);
+
+/* processor_enable.c */
+int processor_flash_enable(void);
+#endif
+
+#if CONFIG_INTERNAL == 1
+/* cbtable.c */
+int cb_parse_table(const char **vendor, const char **model);
+int cb_check_image(const uint8_t *bios, unsigned int size);
+
+/* dmi.c */
+#if defined(__i386__) || defined(__x86_64__)
+void dmi_init(int *is_laptop);
+bool dmi_is_supported(void);
+int dmi_match(const char *pattern);
+#endif // defined(__i386__) || defined(__x86_64__)
+
+/* internal.c */
+struct superio {
+ uint16_t vendor;
+ uint16_t port;
+ uint16_t model;
+};
+extern struct superio superios[];
+extern int superio_count;
+#define SUPERIO_VENDOR_NONE 0x0
+#define SUPERIO_VENDOR_ITE 0x1
+#define SUPERIO_VENDOR_WINBOND 0x2
+#endif
+
+#if CONFIG_INTERNAL == 1
+extern bool force_boardmismatch;
+void probe_superio(void);
+int register_superio(struct superio s);
+extern enum chipbustype internal_buses_supported;
+#endif
+
+/* bitbang_spi.c */
+int register_spi_bitbang_master(const struct bitbang_spi_master *master, void *spi_data);
+
+
+/* flashrom.c */
+struct decode_sizes {
+ uint32_t parallel;
+ uint32_t lpc;
+ uint32_t fwh;
+ uint32_t spi;
+};
+// FIXME: These need to be local, not global
+extern struct decode_sizes max_rom_decode;
+extern bool programmer_may_write;
+extern uintptr_t flashbase; /* used in programmer_enable.c */
+char *extract_programmer_param_str(const struct programmer_cfg *cfg, const char *param_name);
+
+/* spi.c */
+#define MAX_DATA_UNSPECIFIED 0
+#define MAX_DATA_READ_UNLIMITED 64 * 1024
+#define MAX_DATA_WRITE_UNLIMITED 256
+
+#define SPI_MASTER_4BA (1U << 0) /**< Can handle 4-byte addresses */
+#define SPI_MASTER_NO_4BA_MODES (1U << 1) /**< Compatibility modes (i.e. extended address
+ register, 4BA mode switch) don't work */
+
+struct spi_master {
+ uint32_t features;
+ unsigned int max_data_read; // (Ideally,) maximum data read size in one go (excluding opcode+address).
+ unsigned int max_data_write; // (Ideally,) maximum data write size in one go (excluding opcode+address).
+ int (*command)(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr);
+ int (*multicommand)(const struct flashctx *flash, struct spi_command *cmds);
+
+ /* Optimized functions for this master */
+ void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
+ void (*unmap_flash_region) (void *virt_addr, size_t len);
+ int (*read)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+ int (*write_256)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+ int (*write_aai)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+ int (*shutdown)(void *data);
+ bool (*probe_opcode)(const struct flashctx *flash, uint8_t opcode); /* NULL func implies true. */
+ void (*delay) (const struct flashctx *flash, unsigned int usecs);
+ void (*get_region)(const struct flashctx *flash, unsigned int addr, struct flash_region *region);
+ void *data;
+};
+
+int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+int default_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+int register_spi_master(const struct spi_master *mst, void *data);
+
+/* The following enum is needed by ich_descriptor_tool and ich* code as well as in chipset_enable.c. */
+enum ich_chipset {
+ CHIPSET_ICH_UNKNOWN,
+ CHIPSET_ICH,
+ CHIPSET_ICH2345,
+ CHIPSET_ICH6,
+ CHIPSET_POULSBO, /* SCH U* */
+ CHIPSET_TUNNEL_CREEK, /* Atom E6xx */
+ CHIPSET_CENTERTON, /* Atom S1220 S1240 S1260 */
+ CHIPSET_ICH7,
+ CHIPSET_ICH8,
+ CHIPSET_ICH9,
+ CHIPSET_ICH10,
+ CHIPSET_5_SERIES_IBEX_PEAK,
+ CHIPSET_6_SERIES_COUGAR_POINT,
+ CHIPSET_7_SERIES_PANTHER_POINT,
+ CHIPSET_8_SERIES_LYNX_POINT,
+ CHIPSET_BAYTRAIL, /* Actually all with Silvermont architecture: Bay Trail, Avoton/Rangeley */
+ CHIPSET_8_SERIES_LYNX_POINT_LP,
+ CHIPSET_8_SERIES_WELLSBURG,
+ CHIPSET_9_SERIES_WILDCAT_POINT,
+ CHIPSET_9_SERIES_WILDCAT_POINT_LP,
+ CHIPSET_100_SERIES_SUNRISE_POINT, /* also 6th/7th gen Core i/o (LP) variants */
+ CHIPSET_C620_SERIES_LEWISBURG,
+ CHIPSET_300_SERIES_CANNON_POINT,
+ CHIPSET_400_SERIES_COMET_POINT,
+ CHIPSET_500_SERIES_TIGER_POINT,
+ CHIPSET_600_SERIES_ALDER_POINT,
+ CHIPSET_METEOR_LAKE,
+ CHIPSET_APOLLO_LAKE,
+ CHIPSET_GEMINI_LAKE,
+ CHIPSET_JASPER_LAKE,
+ CHIPSET_ELKHART_LAKE,
+};
+
+/* ichspi.c */
+#if CONFIG_INTERNAL == 1
+int ich_init_spi(const struct programmer_cfg *cfg, void *spibar, enum ich_chipset ich_generation);
+int via_init_spi(uint32_t mmio_base);
+
+/* amd_imc.c */
+int amd_imc_shutdown(struct pci_dev *dev);
+
+/* it87spi.c */
+void enter_conf_mode_ite(uint16_t port);
+void exit_conf_mode_ite(uint16_t port);
+void probe_superio_ite(void);
+int init_superio_ite(const struct programmer_cfg *cfg);
+
+/* trivial wrapper to avoid cluttering internal_init() with #if */
+static inline int try_mtd(const struct programmer_cfg *cfg)
+{
+#if CONFIG_LINUX_MTD == 1
+ return programmer_linux_mtd.init(cfg);
+#else
+ return 1;
+#endif
+}
+
+/* mcp6x_spi.c */
+int mcp6x_spi_init(int want_spi);
+
+/* internal_par.c */
+void internal_par_init(enum chipbustype buses);
+
+/* sb600spi.c */
+int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev);
+
+/* wbsio_spi.c */
+int wbsio_check_for_spi(struct board_cfg *);
+#endif
+
+/* opaque.c */
+struct opaque_master {
+ int max_data_read;
+ int max_data_write;
+ /* Specific functions for this master */
+ int (*probe) (struct flashctx *flash);
+ int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+ int (*write) (struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+ int (*erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
+ /*
+ * Callbacks for accessing flash registers. An opaque programmer must
+ * provide these functions for writeprotect operations to be available,
+ * unless it provides custom wp operations instead.
+ */
+ int (*read_register)(const struct flashctx *flash, enum flash_reg reg, uint8_t *value);
+ int (*write_register)(const struct flashctx *flash, enum flash_reg reg, uint8_t value);
+ /* Callbacks for overiding default writeprotect operations with custom ones. */
+ enum flashrom_wp_result (*wp_write_cfg)(struct flashctx *, const struct flashrom_wp_cfg *);
+ enum flashrom_wp_result (*wp_read_cfg)(struct flashrom_wp_cfg *, struct flashctx *);
+ enum flashrom_wp_result (*wp_get_ranges)(struct flashrom_wp_ranges **, struct flashctx *);
+ void (*get_region)(const struct flashctx *flash, unsigned int addr, struct flash_region *region);
+ int (*shutdown)(void *data);
+ void (*delay) (const struct flashctx *flash, unsigned int usecs);
+ void *data;
+};
+int register_opaque_master(const struct opaque_master *mst, void *data);
+
+/* parallel.c */
+struct par_master {
+ void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
+ void (*unmap_flash_region) (void *virt_addr, size_t len);
+ void (*chip_writeb) (const struct flashctx *flash, uint8_t val, chipaddr addr);
+ void (*chip_writew) (const struct flashctx *flash, uint16_t val, chipaddr addr);
+ void (*chip_writel) (const struct flashctx *flash, uint32_t val, chipaddr addr);
+ void (*chip_writen) (const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len);
+ uint8_t (*chip_readb) (const struct flashctx *flash, const chipaddr addr);
+ uint16_t (*chip_readw) (const struct flashctx *flash, const chipaddr addr);
+ uint32_t (*chip_readl) (const struct flashctx *flash, const chipaddr addr);
+ void (*chip_readn) (const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len);
+ int (*shutdown)(void *data);
+ void (*delay) (const struct flashctx *flash, unsigned int usecs);
+ void *data;
+};
+int register_par_master(const struct par_master *mst, const enum chipbustype buses, void *data);
+
+/* programmer.c */
+struct registered_master {
+ enum chipbustype buses_supported;
+ struct {
+ struct par_master par;
+ struct spi_master spi;
+ struct opaque_master opaque;
+ };
+};
+extern struct registered_master registered_masters[];
+extern int registered_master_count;
+int register_master(const struct registered_master *mst);
+
+
+
+/* serial.c */
+#if IS_WINDOWS
+typedef HANDLE fdtype;
+#define SER_INV_FD INVALID_HANDLE_VALUE
+#else
+typedef int fdtype;
+#define SER_INV_FD -1
+#endif
+
+void sp_flush_incoming(void);
+fdtype sp_openserport(char *dev, int baud);
+extern fdtype sp_fd;
+int serialport_config(fdtype fd, int baud);
+int serialport_shutdown(void *data);
+int serialport_write(const unsigned char *buf, unsigned int writecnt);
+int serialport_write_nonblock(const unsigned char *buf, unsigned int writecnt, unsigned int timeout, unsigned int *really_wrote);
+int serialport_read(unsigned char *buf, unsigned int readcnt);
+int serialport_read_nonblock(unsigned char *c, unsigned int readcnt, unsigned int timeout, unsigned int *really_read);
+
+/* Serial port/pin mapping:
+
+ 1 CD <-
+ 2 RXD <-
+ 3 TXD ->
+ 4 DTR ->
+ 5 GND --
+ 6 DSR <-
+ 7 RTS ->
+ 8 CTS <-
+ 9 RI <-
+*/
+enum SP_PIN {
+ PIN_CD = 1,
+ PIN_RXD,
+ PIN_TXD,
+ PIN_DTR,
+ PIN_GND,
+ PIN_DSR,
+ PIN_RTS,
+ PIN_CTS,
+ PIN_RI,
+};
+
+void sp_set_pin(enum SP_PIN pin, int val);
+int sp_get_pin(enum SP_PIN pin);
+
+/* spi_master feature checks */
+static inline bool spi_master_4ba(const struct flashctx *const flash)
+{
+ return flash->mst->buses_supported & BUS_SPI &&
+ flash->mst->spi.features & SPI_MASTER_4BA;
+}
+static inline bool spi_master_no_4ba_modes(const struct flashctx *const flash)
+{
+ return flash->mst->buses_supported & BUS_SPI &&
+ flash->mst->spi.features & SPI_MASTER_NO_4BA_MODES;
+}
+/* spi_chip feature checks */
+static inline bool spi_chip_4ba(const struct flashctx *const flash)
+{
+ return flash->chip->bustype == BUS_SPI &&
+ (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_ENTER_EAR7));
+}
+
+/* usbdev.c */
+struct libusb_device_handle;
+struct libusb_context;
+struct libusb_device_handle *usb_dev_get_by_vid_pid_serial(
+ struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, const char *serialno);
+struct libusb_device_handle *usb_dev_get_by_vid_pid_number(
+ struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, unsigned int num);
+
+
+#endif /* !__PROGRAMMER_H__ */
diff --git a/include/spi.h b/include/spi.h
new file mode 100644
index 000000000..505aecd01
--- /dev/null
+++ b/include/spi.h
@@ -0,0 +1,240 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2007, 2008 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SPI_H__
+#define __SPI_H__ 1
+
+/*
+ * Contains the generic SPI headers
+ */
+
+#define JEDEC_MAX_ADDR_LEN 0x04
+
+/* Read Electronic ID */
+#define JEDEC_RDID 0x9f
+#define JEDEC_RDID_OUTSIZE 0x01
+/* INSIZE may be 0x04 for some chips*/
+#define JEDEC_RDID_INSIZE 0x03
+
+/* Some ST M95X model */
+#define ST_M95_RDID 0x83
+#define ST_M95_RDID_3BA_OUTSIZE 0x04 /* 8b op, 24bit addr where size >64KiB */
+#define ST_M95_RDID_2BA_OUTSIZE 0x03 /* 8b op, 16bit addr where size <=64KiB */
+#define ST_M95_RDID_OUTSIZE_MAX 0x04 /* ST_M95_RDID_3BA_OUTSIZE */
+#define ST_M95_RDID_INSIZE 0x03
+
+/* Some Atmel AT25F* models have bit 3 as don't care bit in commands */
+#define AT25F_RDID 0x15 /* 0x15 or 0x1d */
+#define AT25F_RDID_OUTSIZE 0x01
+#define AT25F_RDID_INSIZE 0x02
+
+/* Read Electronic Manufacturer Signature */
+#define JEDEC_REMS 0x90
+#define JEDEC_REMS_OUTSIZE 0x04
+#define JEDEC_REMS_INSIZE 0x02
+
+/* Read Serial Flash Discoverable Parameters (SFDP) */
+#define JEDEC_SFDP 0x5a
+#define JEDEC_SFDP_OUTSIZE 0x05 /* 8b op, 24b addr, 8b dummy */
+/* JEDEC_SFDP_INSIZE : any length */
+
+/* Read Electronic Signature */
+#define JEDEC_RES 0xab
+#define JEDEC_RES_OUTSIZE 0x04
+/* INSIZE may be 0x02 for some chips*/
+#define JEDEC_RES_INSIZE 0x01
+
+/* Write Enable */
+#define JEDEC_WREN 0x06
+#define JEDEC_WREN_OUTSIZE 0x01
+#define JEDEC_WREN_INSIZE 0x00
+
+/* Write Disable */
+#define JEDEC_WRDI 0x04
+#define JEDEC_WRDI_OUTSIZE 0x01
+#define JEDEC_WRDI_INSIZE 0x00
+
+/* Chip Erase 0x60 is supported by Macronix/SST chips. */
+#define JEDEC_CE_60 0x60
+#define JEDEC_CE_60_OUTSIZE 0x01
+#define JEDEC_CE_60_INSIZE 0x00
+
+/* Chip Erase 0x62 is supported by Atmel AT25F chips. */
+#define JEDEC_CE_62 0x62
+#define JEDEC_CE_62_OUTSIZE 0x01
+#define JEDEC_CE_62_INSIZE 0x00
+
+/* Chip Erase 0xc7 is supported by SST/ST/EON/Macronix chips. */
+#define JEDEC_CE_C7 0xc7
+#define JEDEC_CE_C7_OUTSIZE 0x01
+#define JEDEC_CE_C7_INSIZE 0x00
+
+/* Block Erase 0x50 is supported by Atmel AT26DF chips. */
+#define JEDEC_BE_50 0x50
+#define JEDEC_BE_50_OUTSIZE 0x04
+#define JEDEC_BE_50_INSIZE 0x00
+
+/* Block Erase 0x52 is supported by SST and old Atmel chips. */
+#define JEDEC_BE_52 0x52
+#define JEDEC_BE_52_OUTSIZE 0x04
+#define JEDEC_BE_52_INSIZE 0x00
+
+/* Block Erase 0x81 is supported by Atmel AT26DF chips. */
+#define JEDEC_BE_81 0x81
+#define JEDEC_BE_81_OUTSIZE 0x04
+#define JEDEC_BE_81_INSIZE 0x00
+
+/* Block Erase 0xc4 is supported by Micron chips. */
+#define JEDEC_BE_C4 0xc4
+#define JEDEC_BE_C4_OUTSIZE 0x04
+#define JEDEC_BE_C4_INSIZE 0x00
+
+/* Block Erase 0xd8 is supported by EON/Macronix chips. */
+#define JEDEC_BE_D8 0xd8
+#define JEDEC_BE_D8_OUTSIZE 0x04
+#define JEDEC_BE_D8_INSIZE 0x00
+
+/* Block Erase 0xd7 is supported by PMC chips. */
+#define JEDEC_BE_D7 0xd7
+#define JEDEC_BE_D7_OUTSIZE 0x04
+#define JEDEC_BE_D7_INSIZE 0x00
+
+/* Block Erase 0xdc is supported by Spansion chips, takes 4 byte address */
+#define JEDEC_BE_DC 0xdc
+#define JEDEC_BE_DC_OUTSIZE 0x05
+#define JEDEC_BE_DC_INSIZE 0x00
+
+/* Sector Erase 0x20 is supported by Macronix/SST chips. */
+#define JEDEC_SE 0x20
+#define JEDEC_SE_OUTSIZE 0x04
+#define JEDEC_SE_INSIZE 0x00
+
+/* Page Erase 0xDB */
+#define JEDEC_PE 0xDB
+#define JEDEC_PE_OUTSIZE 0x04
+#define JEDEC_PE_INSIZE 0x00
+
+/* Read Status Register */
+#define JEDEC_RDSR 0x05
+#define JEDEC_RDSR_OUTSIZE 0x01
+#define JEDEC_RDSR_INSIZE 0x01
+
+/* Read Status Register 2 */
+#define JEDEC_RDSR2 0x35
+#define JEDEC_RDSR2_OUTSIZE 0x01
+#define JEDEC_RDSR2_INSIZE 0x01
+
+/* Read Status Register 3 */
+#define JEDEC_RDSR3 0x15
+#define JEDEC_RDSR3_OUTSIZE 0x01
+#define JEDEC_RDSR3_INSIZE 0x01
+
+/* Status Register Bits */
+#define SPI_SR_WIP (0x01 << 0)
+#define SPI_SR_WEL (0x01 << 1)
+#define SPI_SR_ERA_ERR (0x01 << 5)
+#define SPI_SR_AAI (0x01 << 6)
+
+/* Write Status Enable */
+#define JEDEC_EWSR 0x50
+#define JEDEC_EWSR_OUTSIZE 0x01
+#define JEDEC_EWSR_INSIZE 0x00
+
+/* Write Status Register */
+#define JEDEC_WRSR 0x01
+#define JEDEC_WRSR_OUTSIZE 0x02
+#define JEDEC_WRSR_INSIZE 0x00
+
+/* Write Status Register 2 */
+#define JEDEC_WRSR2 0x31
+#define JEDEC_WRSR2_OUTSIZE 0x02
+#define JEDEC_WRSR2_INSIZE 0x00
+
+/* Write Status Register 3 */
+#define JEDEC_WRSR3 0x11
+#define JEDEC_WRSR3_OUTSIZE 0x02
+#define JEDEC_WRSR3_INSIZE 0x00
+
+/* Read Security Register */
+#define JEDEC_RDSCUR 0x2b
+#define JEDEC_RDSCUR_OUTSIZE 0x01
+#define JEDEC_RDSCUR_INSIZE 0x01
+
+/* Write Security Register */
+#define JEDEC_WRSCUR 0x2f
+#define JEDEC_WRSCUR_OUTSIZE 0x01
+#define JEDEC_WRSCUR_INSIZE 0x00
+
+/* Read Configuration Register */
+#define JEDEC_RDCR 0x15
+#define JEDEC_RDCR_OUTSIZE 0x01
+#define JEDEC_RDCR_INSIZE 0x01
+
+/* Enter 4-byte Address Mode */
+#define JEDEC_ENTER_4_BYTE_ADDR_MODE 0xB7
+
+/* Exit 4-byte Address Mode */
+#define JEDEC_EXIT_4_BYTE_ADDR_MODE 0xE9
+
+/* Write Extended Address Register */
+#define JEDEC_WRITE_EXT_ADDR_REG 0xC5
+#define ALT_WRITE_EXT_ADDR_REG_17 0x17
+
+/* Read Extended Address Register */
+#define JEDEC_READ_EXT_ADDR_REG 0xC8
+#define ALT_READ_EXT_ADDR_REG_16 0x16
+
+/* Read the memory */
+#define JEDEC_READ 0x03
+#define JEDEC_READ_OUTSIZE 0x04
+/* JEDEC_READ_INSIZE : any length */
+
+/* Read the memory (with delay after sending address) */
+#define JEDEC_READ_FAST 0x0b
+
+/* Write memory byte */
+#define JEDEC_BYTE_PROGRAM 0x02
+#define JEDEC_BYTE_PROGRAM_OUTSIZE 0x05
+#define JEDEC_BYTE_PROGRAM_INSIZE 0x00
+
+/* Write AAI word (SST25VF080B) */
+#define JEDEC_AAI_WORD_PROGRAM 0xad
+#define JEDEC_AAI_WORD_PROGRAM_OUTSIZE 0x06
+#define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE 0x03
+#define JEDEC_AAI_WORD_PROGRAM_INSIZE 0x00
+
+/* Read the memory with 4-byte address
+ From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
+#define JEDEC_READ_4BA 0x13
+
+/* Read the memory with 4-byte address (and delay after sending address)
+ From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
+#define JEDEC_READ_4BA_FAST 0x0c
+
+/* Write memory byte with 4-byte address
+ From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
+#define JEDEC_BYTE_PROGRAM_4BA 0x12
+
+/* Error codes */
+#define SPI_GENERIC_ERROR -1
+#define SPI_INVALID_OPCODE -2
+#define SPI_INVALID_ADDRESS -3
+#define SPI_INVALID_LENGTH -4
+#define SPI_FLASHROM_BUG -5
+#define SPI_PROGRAMMER_ERROR -6
+
+void clear_spi_id_cache(void);
+
+#endif /* !__SPI_H__ */
diff --git a/include/usb_device.h b/include/usb_device.h
new file mode 100644
index 000000000..ed8187bb3
--- /dev/null
+++ b/include/usb_device.h
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2020, Google Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef USB_DEVICE_H
+#define USB_DEVICE_H
+
+/*
+ * USB device matching framework
+ *
+ * This can be used to match a USB device by a number of different parameters.
+ * The parameters can be passed on the command line and defaults can be set
+ * by the programmer.
+ */
+
+#include <libusb.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/*
+ * The LIBUSB_ERROR macro converts a libusb failure code into an error code that
+ * flashrom recognizes. It does so without displaying an error code allowing us
+ * to compare error codes against the library enumeration values.
+ */
+#define LIBUSB_ERROR(error_code) (0x20000 | -(error_code))
+
+/*
+ * The LIBUSB macro converts a libusb failure code into an error code that
+ * flashrom recognizes. It also displays additional libusb specific
+ * information about the failure.
+ */
+#define LIBUSB(expression) \
+ ({ \
+ int libusb_error__ = (expression); \
+ \
+ if (libusb_error__ < 0) { \
+ msg_perr("libusb error: %s:%d %s\n", \
+ __FILE__, \
+ __LINE__, \
+ libusb_error_name(libusb_error__)); \
+ libusb_error__ = LIBUSB_ERROR(libusb_error__); \
+ } else { \
+ libusb_error__ = 0; \
+ } \
+ \
+ libusb_error__; \
+ })
+
+/*
+ * Returns true if the error code falls within the range of valid libusb
+ * error codes.
+ */
+static inline bool usb_device_is_libusb_error(int error_code)
+{
+ return (0x20000 <= error_code && error_code < 0x20064);
+}
+
+/*
+ * A USB match and associated value struct are used to encode the information
+ * about a device against which we wish to match. If the value of a
+ * usb_match_value has been set then a device must match that value. The name
+ * of the usb_match_value is used to fetch the programmer parameter from the
+ * flashrom command line and is the same as the name of the corresponding
+ * field in usb_match.
+ */
+struct usb_match_value {
+ char const *name;
+ int value;
+ int set;
+};
+
+struct usb_match {
+ struct usb_match_value bus;
+ struct usb_match_value address;
+ struct usb_match_value vid;
+ struct usb_match_value pid;
+ struct usb_match_value serial;
+ struct usb_match_value config;
+ struct usb_match_value interface;
+ struct usb_match_value altsetting;
+ struct usb_match_value class;
+ struct usb_match_value subclass;
+ struct usb_match_value protocol;
+};
+
+/*
+ * Initialize a usb_match structure so that each value's name matches the
+ * values name in the usb_match structure (so bus.name == "bus"...), and
+ * look for each value in the flashrom command line via
+ * extract_programmer_param_str. If the value is found convert it to an integer
+ * using strtol, accepting hex, decimal and octal encoding.
+ */
+void usb_match_init(const struct programmer_cfg *cfg, struct usb_match *match);
+
+/*
+ * Add a default value to a usb_match_value. This must be done after calling
+ * usb_match_init. If usb_match_init already set the value of a usb_match_value
+ * we do nothing, otherwise set the value to default_value. This ensures that
+ * parameters passed on the command line override defaults.
+ */
+void usb_match_value_default(struct usb_match_value *match,
+ long int default_value);
+
+/*
+ * The usb_device structure is an entry in a linked list of devices that were
+ * matched by usb_device_find.
+ */
+struct usb_device {
+ struct libusb_device *device;
+ struct libusb_config_descriptor *config_descriptor;
+ struct libusb_interface_descriptor const *interface_descriptor;
+
+ /*
+ * Initially NULL, the libusb_device_handle is only valid once the
+ * usb_device has been successfully passed to usb_device_show or
+ * usb_device_claim.
+ */
+ struct libusb_device_handle *handle;
+
+ /*
+ * Link to next device, or NULL
+ */
+ struct usb_device *next;
+};
+
+/*
+ * Find and return a list of all compatible devices. Each device is added to
+ * the list with its first valid configuration and interface. If an alternate
+ * configuration (config, interface, altsetting...) is desired the specifics
+ * can be supplied as programmer parameters.
+ *
+ * Return:
+ * 0: At least one matching device was found.
+ * 1: No matching devices were found.
+ */
+int usb_device_find(struct usb_match const *match, struct usb_device **devices);
+
+/*
+ * Display the devices bus and address as well as its product string. The
+ * underlying libusb device is opened if it is not already open.
+ *
+ * Return:
+ * 0: The device information was displayed.
+ * non-zero: There was a failure while displaying the device information.
+ */
+int usb_device_show(char const *prefix, struct usb_device *device);
+
+/*
+ * Open the underlying libusb device, set its config, claim the interface and
+ * select the correct alternate interface.
+ *
+ * Return:
+ * 0: The device was successfully claimed.
+ * non-zero: There was a failure while trying to claim the device.
+ */
+int usb_device_claim(struct usb_device *device);
+
+/*
+ * Free a usb_device structure.
+ *
+ * This ensures that the libusb device is closed and that all allocated
+ * handles and descriptors are freed.
+ *
+ * Return:
+ * The next device in the device list.
+ */
+struct usb_device *usb_device_free(struct usb_device *device);
+
+#endif /* USB_DEVICE_H */
diff --git a/include/writeprotect.h b/include/writeprotect.h
new file mode 100644
index 000000000..7ceed0792
--- /dev/null
+++ b/include/writeprotect.h
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __WRITEPROTECT_H__
+#define __WRITEPROTECT_H__ 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "libflashrom.h"
+
+#define MAX_BP_BITS 4
+
+/* Chip protection range: start address and length. */
+struct wp_range {
+ size_t start, len;
+};
+
+/* Generic description of a chip's write protection configuration. */
+struct flashrom_wp_cfg {
+ enum flashrom_wp_mode mode;
+ struct wp_range range;
+};
+
+/* Collection of multiple write protection ranges. */
+struct flashrom_wp_ranges {
+ struct wp_range *ranges;
+ size_t count;
+};
+
+/*
+ * Description of a chip's write protection configuration.
+ *
+ * It allows most WP code to store and manipulate a chip's configuration
+ * without knowing the exact layout of bits in the chip's status registers.
+ */
+struct wp_bits {
+ /* Status register protection bit (SRP) */
+ bool srp_bit_present;
+ uint8_t srp;
+
+ /* Status register lock bit (SRL) */
+ bool srl_bit_present;
+ uint8_t srl;
+
+ /* Complement bit (CMP) */
+ bool cmp_bit_present;
+ uint8_t cmp;
+
+ /* Sector/block protection bit (SEC) */
+ bool sec_bit_present;
+ uint8_t sec;
+
+ /* Top/bottom protection bit (TB) */
+ bool tb_bit_present;
+ uint8_t tb;
+
+ /* Block protection bits (BP) */
+ size_t bp_bit_count;
+ uint8_t bp[MAX_BP_BITS];
+};
+
+struct flashrom_flashctx;
+
+/* Write WP configuration to the chip */
+enum flashrom_wp_result wp_write_cfg(struct flashrom_flashctx *, const struct flashrom_wp_cfg *);
+
+/* Read WP configuration from the chip */
+enum flashrom_wp_result wp_read_cfg(struct flashrom_wp_cfg *, struct flashrom_flashctx *);
+
+/* Get a list of protection ranges supported by the chip */
+enum flashrom_wp_result wp_get_available_ranges(struct flashrom_wp_ranges **, struct flashrom_flashctx *);
+
+/* Checks if writeprotect functions can be used with the current flash/programmer */
+bool wp_operations_available(struct flashrom_flashctx *);
+
+/*
+ * Converts a writeprotect config to register values and masks that indicate which register bits affect WP state.
+ * reg_values, bit_masks, and write_masks must all have length of at least MAX_REGISTERS.
+ */
+enum flashrom_wp_result wp_cfg_to_reg_values(uint8_t *reg_values, uint8_t *bit_masks, uint8_t *write_masks, struct flashrom_flashctx *, const struct flashrom_wp_cfg *);
+
+#endif /* !__WRITEPROTECT_H__ */