summaryrefslogtreecommitdiffstats
path: root/util/cbfstool/fpt_formats/fpt_hdr_20.c
blob: 166d24cdf06c370929a6df5cd9c68b3d5b7e8839 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/* CSE FPT header version 0x20 */
/* SPDX-License-Identifier: GPL-2.0-only */

#include <sys/types.h>

#include "cse_fpt.h"

struct fpt_hdr {
	uint8_t marker[4];		/* FPT_MARKER */
	uint32_t num_entries;
	uint8_t hdr_version;		/* FPT_HDR_VERSION_20 */
	uint8_t entry_version;		/* FPT_ENTRY_VERSION */
	uint8_t hdr_length;
	uint8_t hdr_checksum;
	uint8_t rsvd[20];
} __packed;

static bool match_version(struct buffer *buff)
{
	const uint8_t *data = buffer_get(buff);
	uint8_t version = read_at_le8(data, offsetof(struct fpt_hdr, hdr_version));

	return version == FPT_HDR_VERSION_20;
}

static bool validate_fpt_hdr(const struct fpt_hdr *h)
{
	if (memcmp(h->marker, FPT_MARKER, sizeof(h->marker))) {
		ERROR("Invalid FPT header marker!\n");
		return false;
	}

	if (h->hdr_version != FPT_HDR_VERSION_20) {
		ERROR("Invalid FPT header version(0x%x)!\n", h->hdr_version);
		return false;
	}

	if (h->entry_version != FPT_ENTRY_VERSION) {
		ERROR("Invalid FPT entry version(0x%x)!\n", h->entry_version);
		return false;
	}

	const uint8_t *data = (const uint8_t *)h;
	uint8_t checksum = 0;

	for (size_t i = 0; i < sizeof(*h); i++)
		checksum += data[i];

	if (checksum != 0) {
		ERROR("Invalid checksum (0x%x)!\n", h->hdr_checksum);
		return false;
	}

	return true;
}

static fpt_hdr_ptr read_fpt_hdr(struct buffer *buff)
{
	struct fpt_hdr *h = malloc(sizeof(*h));
	if (!h)
		return NULL;

	READ_MEMBER(buff, h->marker);
	READ_MEMBER(buff, h->num_entries);
	READ_MEMBER(buff, h->hdr_version);
	READ_MEMBER(buff, h->entry_version);
	READ_MEMBER(buff, h->hdr_length);
	READ_MEMBER(buff, h->hdr_checksum);
	READ_MEMBER(buff, h->rsvd);

	if (!validate_fpt_hdr(h)) {
		free(h);
		return NULL;
	}

	return h;
}

static void print_fpt_hdr(const fpt_hdr_ptr ptr)
{
	struct fpt_hdr *h = ptr;

	printf(" * FPT header\n");
	printf("%-25s: %.4s\n", "Marker", h->marker);
	printf("%-25s: %d\n", "Number of entries", h->num_entries);
	printf("%-25s: 0x%x\n", "Header version", h->hdr_version);
	printf("%-25s: 0x%x\n", "Entry version", h->entry_version);
	printf("%-25s: %d\n", "Header length", h->hdr_length);
	printf("%-25s: 0x%x\n", "Header checksum", h->hdr_checksum);
}

static size_t get_entry_count(const fpt_hdr_ptr ptr)
{
	struct fpt_hdr *h = ptr;

	return h->num_entries;
}

const struct fpt_hdr_ops fpt_hdr_20_ops = {
	.match_version = match_version,

	.read = read_fpt_hdr,
	.print = print_fpt_hdr,

	.get_entry_count = get_entry_count,
};