On Fri, 2023-05-05 at 09:04 -0700, Ceraolo Spurio, Daniele wrote:

alan: snip


> +int intel_gsc_fw_get_binary_info(struct intel_uc_fw *gsc_fw, const void 
> *data, size_t size)
> +{
alan:snip
> +     /*
> +      * The GSC binary starts with the pointer layout, which contains the
> +      * locations of the various partitions of the binary. The one we're
> +      * interested in to get the version is the boot1 partition, where we can
> +      * find a BPDT header followed by entries, one of which points to the
> +      * RBE sub-section of the partition. From here, we can parse the CPD
alan: nit: could we add the meaning of 'RBE', probably not here but in the 
header file where GSC_RBE is defined?
> +      * header and the following entries to find the manifest location
> +      * (entry identified by the "RBEP.man" name), from which we can finally
> +      * extract the version.
> +      *
> +      * --------------------------------------------------
> +      * [  intel_gsc_layout_pointers                     ]
> +      * [      ...                                       ]
> +      * [      boot1_offset  >---------------------------]------o
> +      * [      ...                                       ]      |
> +      * --------------------------------------------------      |
> +      *                                                         |
> +      * --------------------------------------------------      |
> +      * [  intel_gsc_bpdt_header                         ]<-----o
> +      * --------------------------------------------------
alan: special thanks for the diagram - love these! :)
alan: snip

> +     min_size = layout->boot1_offset + layout->boot1_offset > size;
alan: latter is a binary so + 1? or is this a typo and supposed to be:
        min_size = layout->boot1_offset;
actually since we are accessing a bpdt_header hanging off that offset, it 
should rather be:
        min_size = layout->boot1_offset + sizeof(*bpdt_header);
> +     if (size < min_size) {
> +             gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n",
> +                    size, min_size);
> +             return -ENODATA;
> +     }
> +
> +     bpdt_header = data + layout->boot1_offset;
> +     if (bpdt_header->signature != INTEL_GSC_BPDT_HEADER_SIGNATURE) {
> +             gt_err(gt, "invalid signature for meu BPDT header: 0x%08x!\n",
> +                    bpdt_header->signature);
> +             return -EINVAL;
> +     }
> +
alan: IIUC, to be strict about the size-crawl-checking, we should check minsize
again - this time with the additional "bpdt_header->descriptor_count * 
sizeof(*bpdt_entry)".
(hope i got that right?) - adding that check before parsing through the 
(bpdt_entry++)'s ->type
> +     bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);
> +     for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) {
> +             if ((bpdt_entry->type & INTEL_GSC_BPDT_ENTRY_TYPE_MASK) !=
> +                 INTEL_GSC_BPDT_ENTRY_TYPE_GSC_RBE)
> +                     continue;
> +
> +             cpd_header = (void *)bpdt_header + 
> bpdt_entry->sub_partition_offset;
> +             break;
> +     }
> +
> +     if (!cpd_header) {
> +             gt_err(gt, "couldn't find CPD header in GSC binary!\n");
> +             return -ENODATA;
> +     }
alan: same as above, so for size-crawl-checking, we should check minsize again 
with the addition of cpd_header, no?
> +
> +     if (cpd_header->header_marker != INTEL_GSC_CPD_HEADER_MARKER) {
> +             gt_err(gt, "invalid marker for meu CPD header in GSC bin: 
> 0x%08x!\n",
> +                    cpd_header->header_marker);
> +             return -EINVAL;
> +     }
alan: and again here, the size crawl checking with cpd_header->num_of_entries * 
*cpd_entry
> +     cpd_entry = (void *)cpd_header + cpd_header->header_length;
> +     for (i = 0; i < cpd_header->num_of_entries; i++, cpd_entry++) {
> +             if (strcmp(cpd_entry->name, "RBEP.man") == 0) {
> +                     manifest = (void *)cpd_header + 
> cpd_entry_offset(cpd_entry);
> +                     intel_uc_fw_version_from_meu_manifest(&gsc->release,
> +                                                           manifest);
> +                     gsc->security_version = manifest->security_version;
> +                     break;
> +             }
> +     }
> +
> +     return 0;

alan:snip

>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h
> index fff8928218df..8d7b9e4f1ffc 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h
alan:snip


> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_meu_headers.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_gsc_meu_headers.h
> index d55a66202576..8bce2b8aed84 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_meu_headers.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_meu_headers.h
alan:snip



> +struct intel_gsc_layout_pointers {
> +     u8 rom_bypass_vector[16];
alan:snip...
> +     u32 temp_pages_offset;
> +     u32 temp_pages_size;
> +} __packed;

alan: structure layout seems unnecessarily repetitive... why not ->
struct partition_info {
        u32 offset;
        u32 size;
};
struct intel_gsc_layout_pointers {
        u8 rom_bypass_vector[16];
        ...
        struct partition_info datap;
        struct partition_info bootregion[5];
        struct partition_info trace;
}__packed;


> +
alan: we should put the 'bpdt' acronym meaning and if its an intel specific
name, then a bit of additional comment explaining what it means.
> +struct intel_gsc_bpdt_header {
> +     u32 signature;
> +#define INTEL_GSC_BPDT_HEADER_SIGNATURE 0x000055AA
> +
> +     u16 descriptor_count; /* bum of entries after the header */
alan:s/bum/num
> +
> +     u8 version;
> +     u8 configuration;
> +
> +     u32 crc32;
> +
> +     u32 build_version;
> +     struct intel_gsc_meu_version tool_version;
alan: nit: "struct intel_gsc_meu_version meu_version" is better no?
> +} __packed;
> +
> +
> +struct intel_gsc_bpdt_entry {
> +     /*
> +      * Bits 0-15: BPDT entry type
> +      * Bits 16-17: reserved
> +      * Bit 18: code sub-partition
> +      * Bits 19-31: reserved
> +      */
alan: nit: i think its neater to just put above comments next to the #defines 
on the lines following 'type' and
create a genmask for code-sub-partition (if we use it, else skip it?) - the 
benefit being a little less clutter

> +     u32 type;
> +#define INTEL_GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15,0)
> +#define INTEL_GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1
> +
> +     u32 sub_partition_offset; /* from the base of the BPDT header */
> +     u32 sub_partition_size;
> +} __packed;
> +
alan:snip


> --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
> @@ -17,6 +17,9 @@ struct intel_gsc_uc {
>       struct intel_uc_fw fw;
> 
>       /* GSC-specific additions */
> +     struct intel_uc_fw_ver release;

> +     u32 security_version;
alan: for consistency and less redundancy, can't we add "security_version"
into 'struct intel_uc_fw_ver' (which is zero for firmware that doesn't
have it). That way, intel_gsc_uc can re-use intel_uc_fw.file_selected
just like huc?

alan:snip



> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
> index 0a0bd5504057..0c01d48b1dd9 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
alan:snip


> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> index 796f54a62eef..cd8fc194f7fa 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
alan:snip

> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
> index 8f2306627332..279244744d43 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
alan:snip

Reply via email to