[flashrom] [PATCH 1/3] Refine Flash Component descriptor handling.

Marc Jones marcj303 at gmail.com
Wed Aug 13 01:01:42 CEST 2014


On Fri, Aug 1, 2014 at 6:39 PM, Stefan Tauner
<stefan.tauner at alumni.tuwien.ac.at> wrote:
> Possible values as well as encodings have changed in newer chipsets as follows.
>  - Pre-PCH (i.e. ICH) chipsets had a maximum frequency of 33 MHz for all
>    operations
>  - Since Cougar Point the chipsets support dual output fast reads (encoded
>    in bit 30).
>  - Flash component density encoding has changed from 3 to 4 bits with Lynx
>    Point, currently allowing for up to 64 MB chips.
>
> Signed-off-by: Stefan Tauner <stefan.tauner at alumni.tuwien.ac.at>
> ---
>  ich_descriptors.c                                | 182 +++++++++++++++++------
>  ich_descriptors.h                                |  39 ++++-
>  ichspi.c                                         |  24 ++-
>  util/ich_descriptors_tool/ich_descriptors_tool.c |   4 +
>  4 files changed, 193 insertions(+), 56 deletions(-)
>
> diff --git a/ich_descriptors.c b/ich_descriptors.c
> index 528717b..3977a4b 100644
> --- a/ich_descriptors.c
> +++ b/ich_descriptors.c
> @@ -64,7 +64,7 @@ void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity)
>  void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
>  {
>         prettyprint_ich_descriptor_content(&desc->content);
> -       prettyprint_ich_descriptor_component(desc);
> +       prettyprint_ich_descriptor_component(cs, desc);
>         prettyprint_ich_descriptor_region(desc);
>         prettyprint_ich_descriptor_master(&desc->master);
>  #ifdef ICH_DESCRIPTORS_FROM_DUMP
> @@ -98,28 +98,97 @@ void prettyprint_ich_descriptor_content(const struct ich_desc_content *cont)
>         msg_pdbg2("\n");
>  }
>
> -void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc)
> +static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
> +{
> +       if (idx > 1) {
> +               msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
> +               return NULL;
> +       }
> +
> +       if (desc->content.NC == 0 && idx > 0)
> +               return "unused";
> +
> +       static const char * const size_str[] = {
> +               "512 kB",       /* 0000 */
> +               "1 MB",         /* 0001 */
> +               "2 MB",         /* 0010 */
> +               "4 MB",         /* 0011 */
> +               "8 MB",         /* 0100 */
> +               "16 MB",        /* 0101 */ /* Maximum up to Lynx Point (excl.) */
> +               "32 MB",        /* 0110 */
> +               "64 MB",        /* 0111 */
> +       };
> +
> +       switch (cs) {
> +       case CHIPSET_ICH8:
> +       case CHIPSET_ICH9:
> +       case CHIPSET_ICH10:
> +       case CHIPSET_5_SERIES_IBEX_PEAK:
> +       case CHIPSET_6_SERIES_COUGAR_POINT:
> +       case CHIPSET_7_SERIES_PANTHER_POINT: {
> +               uint8_t size_enc;
> +               if (idx == 0) {
> +                       size_enc = desc->component.old.comp1_density;
> +               } else {
> +                       size_enc = desc->component.old.comp2_density;
> +               }
> +               if (size_enc > 5)
> +                       return "reserved";
> +               return size_str[size_enc];
> +       }
> +       case CHIPSET_8_SERIES_LYNX_POINT:
> +       case CHIPSET_8_SERIES_LYNX_POINT_LP:
> +       case CHIPSET_8_SERIES_WELLSBURG: {
> +               uint8_t size_enc;
> +               if (idx == 0) {
> +                       size_enc = desc->component.new.comp1_density;
> +               } else {
> +                       size_enc = desc->component.new.comp2_density;
> +               }
> +               if (size_enc > 7)
> +                       return "reserved";
> +               return size_str[size_enc];
> +       }
> +       case CHIPSET_ICH_UNKNOWN:
> +       default:
> +               return "unknown";
> +       }
> +}
> +
> +static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
>  {
>         static const char * const freq_str[8] = {
>                 "20 MHz",       /* 000 */
>                 "33 MHz",       /* 001 */
>                 "reserved",     /* 010 */
>                 "reserved",     /* 011 */
> -               "50 MHz",       /* 100 */
> +               "50 MHz",       /* 100 */ /* New since Ibex Peak */
>                 "reserved",     /* 101 */
>                 "reserved",     /* 110 */
>                 "reserved"      /* 111 */
>         };
> -       static const char * const size_str[8] = {
> -               "512 kB",       /* 000 */
> -               "  1 MB",       /* 001 */
> -               "  2 MB",       /* 010 */
> -               "  4 MB",       /* 011 */
> -               "  8 MB",       /* 100 */
> -               " 16 MB",       /* 101 */
> -               "reserved",     /* 110 */
> -               "reserved",     /* 111 */
> -       };
> +
> +       switch (cs) {
> +       case CHIPSET_ICH8:
> +       case CHIPSET_ICH9:
> +       case CHIPSET_ICH10:
> +               if (value > 1)
> +                       return "reserved";
> +       case CHIPSET_5_SERIES_IBEX_PEAK:
> +       case CHIPSET_6_SERIES_COUGAR_POINT:
> +       case CHIPSET_7_SERIES_PANTHER_POINT:
> +       case CHIPSET_8_SERIES_LYNX_POINT:
> +       case CHIPSET_8_SERIES_LYNX_POINT_LP:
> +       case CHIPSET_8_SERIES_WELLSBURG:
> +               return freq_str[value];
> +       case CHIPSET_ICH_UNKNOWN:
> +       default:
> +               return "unknown";
> +       }
> +}
> +
> +void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
> +{
>
>         msg_pdbg2("=== Component Section ===\n");
>         msg_pdbg2("FLCOMP   0x%08x\n", desc->component.FLCOMP);
> @@ -127,24 +196,21 @@ void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc)
>         msg_pdbg2("\n");
>
>         msg_pdbg2("--- Details ---\n");
> -       msg_pdbg2("Component 1 density:           %s\n",
> -                 size_str[desc->component.comp1_density]);
> +       msg_pdbg2("Component 1 density:            %s\n", pprint_density(cs, desc, 0));
>         if (desc->content.NC)
> -               msg_pdbg2("Component 2 density:           %s\n",
> -                         size_str[desc->component.comp2_density]);
> +               msg_pdbg2("Component 2 density:            %s\n", pprint_density(cs, desc, 1));
>         else
>                 msg_pdbg2("Component 2 is not used.\n");
> -       msg_pdbg2("Read Clock Frequency:           %s\n",
> -                 freq_str[desc->component.freq_read]);
> -       msg_pdbg2("Read ID and Status Clock Freq.: %s\n",
> -                 freq_str[desc->component.freq_read_id]);
> -       msg_pdbg2("Write and Erase Clock Freq.:    %s\n",
> -                 freq_str[desc->component.freq_write]);
> -       msg_pdbg2("Fast Read is %ssupported.\n",
> -                 desc->component.fastread ? "" : "not ");
> -       if (desc->component.fastread)
> +       msg_pdbg2("Read Clock Frequency:           %s\n", pprint_freq(cs, desc->component.common.freq_read));
> +       msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.common.freq_read_id));
> +       msg_pdbg2("Write and Erase Clock Freq.:    %s\n", pprint_freq(cs, desc->component.common.freq_write));
> +       msg_pdbg2("Fast Read is %ssupported.\n", desc->component.common.fastread ? "" : "not ");
> +       if (desc->component.common.fastread)
>                 msg_pdbg2("Fast Read Clock Frequency:      %s\n",
> -                         freq_str[desc->component.freq_fastread]);
> +                         pprint_freq(cs, desc->component.common.freq_fastread));
> +       if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
> +               msg_pdbg2("Dual Output Fast Read Support:  %sabled\n",
> +                         desc->component.new.dual_output ? "dis" : "en");
>         if (desc->component.FLILL == 0)
>                 msg_pdbg2("No forbidden opcodes.\n");
>         else {
> @@ -273,7 +339,7 @@ static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t of
>         msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
>
>         off *= 4;
> -       switch(conf){
> +       switch (conf){
>         case 0:
>                 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
>                 break;
> @@ -723,29 +789,57 @@ int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, struc
>  #else /* ICH_DESCRIPTORS_FROM_DUMP */
>
>  /** Returns the integer representation of the component density with index
> -idx in bytes or 0 if a correct size can not be determined. */
> -int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx)
> +\em idx in bytes or -1 if the correct size can not be determined. */
> +int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
>  {
> +       if (idx > 1) {
> +               msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
> +               return -1;
> +       }
> +
> +       if (desc->content.NC == 0 && idx > 0)
> +               return 0;
> +
>         uint8_t size_enc;
> -
> -       switch(idx) {
> -       case 0:
> -               size_enc = desc->component.comp1_density;
> +       uint8_t size_max;
> +
> +       switch (cs) {
> +       case CHIPSET_ICH8:
> +       case CHIPSET_ICH9:
> +       case CHIPSET_ICH10:
> +       case CHIPSET_5_SERIES_IBEX_PEAK:
> +       case CHIPSET_6_SERIES_COUGAR_POINT:
> +       case CHIPSET_7_SERIES_PANTHER_POINT:
> +               if (idx == 0) {
> +                       size_enc = desc->component.old.comp1_density;
> +               } else {
> +                       size_enc = desc->component.old.comp2_density;
> +               }
> +               size_max = 5;
>                 break;
> -       case 1:
> -               if (desc->content.NC == 0)
> -                       return 0;
> -               size_enc = desc->component.comp2_density;
> +       case CHIPSET_8_SERIES_LYNX_POINT:
> +       case CHIPSET_8_SERIES_LYNX_POINT_LP:
> +       case CHIPSET_8_SERIES_WELLSBURG:
> +               if (idx == 0) {
> +                       size_enc = desc->component.new.comp1_density;
> +               } else {
> +                       size_enc = desc->component.new.comp2_density;
> +               }
> +               size_max = 7;
>                 break;
> +       case CHIPSET_ICH_UNKNOWN:
>         default:
> -               msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
> -               return 0;
> +               msg_pwarn("Density encoding is unknown on this chipset.\n");
> +               return -1;
>         }
> -       if (size_enc > 5) {
> -               msg_perr("Density of ICH SPI component with index %d is invalid. Encoded density is 0x%x.\n",
> -                        idx, size_enc);
> -               return 0;
> +
> +       if (size_enc > size_max) {
> +               msg_perr("Density of ICH SPI component with index %d is invalid."
> +                        "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
> +                        idx, size_enc, size_max);
> +               return -1;
>         }
> +
>         return (1 << (19 + size_enc));
>  }
>
> diff --git a/ich_descriptors.h b/ich_descriptors.h
> index 3a44740..b9213c8 100644
> --- a/ich_descriptors.h
> +++ b/ich_descriptors.h
> @@ -102,17 +102,44 @@ struct ich_desc_content {
>  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              ?? (multi I/O)  ?       ?:?, ?:?
> +                */
>                 struct {
> -                       uint32_t comp1_density  :3,
> -                                comp2_density  :3,
> -                                               :11,
> +                       uint32_t                :17,
>                                  freq_read      :3,
>                                  fastread       :1,
>                                  freq_fastread  :3,
>                                  freq_write     :3,
>                                  freq_read_id   :3,
>                                                 :2;
> -               };
> +               } common;
> +               struct {
> +                       uint32_t comp1_density  :3,
> +                                comp2_density  :3,
> +                                               :11,
> +                                               :13,
> +                                               :2;
> +               } old;
> +               struct {
> +                       uint32_t comp1_density  :4, /* new since Lynx Point/8 */
> +                                comp2_density  :4,
> +                                               :9,
> +                                               :13,
> +                                dual_output    :1, /* new since Cougar Point/6 */
> +                                               :1;
> +               } new;
>         };
>         union {                 /* 0x04 */
>                 uint32_t FLILL; /* Flash Invalid Instructions Register */
> @@ -555,7 +582,7 @@ struct ich_descriptors {
>  void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc);
>
>  void prettyprint_ich_descriptor_content(const struct ich_desc_content *content);
> -void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc);
> +void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc);
>  void prettyprint_ich_descriptor_region(const struct ich_descriptors *desc);
>  void prettyprint_ich_descriptor_master(const struct ich_desc_master *master);
>
> @@ -568,7 +595,7 @@ int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, struc
>  #else /* ICH_DESCRIPTORS_FROM_DUMP */
>
>  int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc);
> -int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx);
> +int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx);
>
>  #endif /* ICH_DESCRIPTORS_FROM_DUMP */
>  #endif /* __ICH_DESCRIPTORS_H__ */
> diff --git a/ichspi.c b/ichspi.c
> index 90bb0de..6744bef 100644
> --- a/ichspi.c
> +++ b/ichspi.c
> @@ -1754,10 +1754,9 @@ int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_gen)
>
>                 msg_pdbg("\n");
>                 if (desc_valid) {
> -                       if (read_ich_descriptors_via_fdo(ich_spibar, &desc) ==
> -                           ICH_RET_OK)
> -                               prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN,
> -                                                           &desc);
> +                       if (read_ich_descriptors_via_fdo(ich_spibar, &desc) == ICH_RET_OK)
> +                               prettyprint_ich_descriptors(ich_gen, &desc);
> +
>                         /* If the descriptor is valid and indicates multiple
>                          * flash devices we need to use hwseq to be able to
>                          * access the second flash device.
> @@ -1783,8 +1782,21 @@ int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_gen)
>                                          "valid. Aborting.\n");
>                                 return ERROR_FATAL;
>                         }
> -                       hwseq_data.size_comp0 = getFCBA_component_density(&desc, 0);
> -                       hwseq_data.size_comp1 = getFCBA_component_density(&desc, 1);
> +
> +                       int tmpi = getFCBA_component_density(ich_generation, &desc, 0);
> +                       if (tmpi < 0) {
> +                               msg_perr("Could not determine density of flash component %d.\n", 0);
> +                               return ERROR_FATAL;
> +                       }
> +                       hwseq_data.size_comp0 = tmpi;
> +
> +                       tmpi = getFCBA_component_density(ich_generation, &desc, 1);
> +                       if (tmpi < 0) {
> +                               msg_perr("Could not determine density of flash component %d.\n", 1);
> +                               return ERROR_FATAL;
> +                       }
> +                       hwseq_data.size_comp1 = tmpi;
> +
>                         register_opaque_master(&opaque_master_ich_hwseq);
>                 } else {
>                         register_spi_master(&spi_master_ich9);
> diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c
> index 00ad1f3..4c1f05c 100644
> --- a/util/ich_descriptors_tool/ich_descriptors_tool.c
> +++ b/util/ich_descriptors_tool/ich_descriptors_tool.c
> @@ -121,6 +121,7 @@ static void usage(char *argv[], char *error)
>  "\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n"
>  "\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n"
>  "\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n"
> +"\t- \"8\" or \"lynx\" for Intel's 8 series chipsets.\n"
>  "If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n"
>  "the GbE blob that is required to initialize the GbE are also dumped to files.\n",
>         argv[0], argv[0]);
> @@ -198,6 +199,9 @@ int main(int argc, char *argv[])
>                 else if ((strcmp(csn, "7") == 0) ||
>                          (strcmp(csn, "panther") == 0))
>                         cs = CHIPSET_7_SERIES_PANTHER_POINT;
> +               else if ((strcmp(csn, "8") == 0) ||
> +                        (strcmp(csn, "lynx") == 0))
> +                       cs = CHIPSET_8_SERIES_LYNX_POINT;
>         }
>
>         ret = read_ich_descriptors_from_dump(buf, len, &desc);
> --
> Kind regards, Stefan Tauner
>
>
> _______________________________________________
> flashrom mailing list
> flashrom at flashrom.org
> http://www.flashrom.org/mailman/listinfo/flashrom

I tested this branch on CC2: https://github.com/stefanct/flashrom/tree/intel

See attached logs.


Flashrom views both chips as a single flash space. What is the correct
method for only updating a single descriptor area?
 Note that the descriptor allows r/w everything. I have not tried
locking down regions.

LGTM Acked-By:Tested-by: Marc Jones <marcj303 at gmail.com>




-- 
http://se-eng.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cc2-flashrom-stefanct-intel-test
Type: application/octet-stream
Size: 1393275 bytes
Desc: not available
URL: <http://www.flashrom.org/pipermail/flashrom/attachments/20140812/3830271f/attachment.obj>


More information about the flashrom mailing list