Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * Parse flash sub-partitions
4 : : *
5 : : * Copyright 2013-2018 IBM Corp.
6 : : */
7 : :
8 : : #include <skiboot.h>
9 : : #include <opal-api.h>
10 : :
11 : : struct flash_hostboot_toc {
12 : : be32 ec;
13 : : be32 offset; /* From start of header. 4K aligned */
14 : : be32 size;
15 : : };
16 : : #define FLASH_HOSTBOOT_TOC_MAX_ENTRIES ((FLASH_SUBPART_HEADER_SIZE - 8) \
17 : : /sizeof(struct flash_hostboot_toc))
18 : :
19 : : struct flash_hostboot_header {
20 : : char eyecatcher[4];
21 : : be32 version;
22 : : struct flash_hostboot_toc toc[FLASH_HOSTBOOT_TOC_MAX_ENTRIES];
23 : : };
24 : :
25 : 5 : int flash_subpart_info(void *part_header, uint32_t header_len,
26 : : uint32_t part_size, uint32_t *part_actualp,
27 : : uint32_t subid, uint32_t *offset, uint32_t *size)
28 : : {
29 : : struct flash_hostboot_header *header;
30 : : char eyecatcher[5];
31 : : uint32_t i, ec, o, s;
32 : : uint32_t part_actual;
33 : : bool subpart_found;
34 : :
35 : 5 : if (!part_header || ( !offset && !size && !part_actualp)) {
36 : 0 : prlog(PR_ERR, "FLASH: invalid parameters: ph %p of %p sz %p "
37 : : "tsz %p\n", part_header, offset, size, part_actualp);
38 : 0 : return OPAL_PARAMETER;
39 : : }
40 : :
41 : 5 : if (header_len < FLASH_SUBPART_HEADER_SIZE) {
42 : 0 : prlog(PR_ERR, "FLASH: subpartition header too small 0x%x\n",
43 : : header_len);
44 : 0 : return OPAL_PARAMETER;
45 : : }
46 : :
47 : 5 : header = (struct flash_hostboot_header*) part_header;
48 : :
49 : : /* Perform sanity */
50 : 5 : i = be32_to_cpu(header->version);
51 : 5 : if (i != 1) {
52 : 0 : prerror("FLASH: flash subpartition TOC version unknown %i\n", i);
53 : 0 : return OPAL_RESOURCE;
54 : : }
55 : :
56 : : /* NULL terminate eyecatcher */
57 : 5 : strncpy(eyecatcher, header->eyecatcher, 4);
58 : 5 : eyecatcher[4] = '\0';
59 : 5 : prlog(PR_DEBUG, "FLASH: flash subpartition eyecatcher %s\n",
60 : : eyecatcher);
61 : :
62 : 5 : subpart_found = false;
63 : 5 : part_actual = 0;
64 : 30 : for (i = 0; i < FLASH_HOSTBOOT_TOC_MAX_ENTRIES; i++) {
65 : :
66 : 30 : ec = be32_to_cpu(header->toc[i].ec);
67 : 30 : o = be32_to_cpu(header->toc[i].offset);
68 : 30 : s = be32_to_cpu(header->toc[i].size);
69 : :
70 : : /* Check for null terminating entry */
71 : 30 : if (!ec && !o && !s)
72 : 5 : break;
73 : :
74 : : /* Sanity check the offset and size. */
75 : 25 : if (o + s > part_size) {
76 : 0 : prerror("FLASH: flash subpartition too big: %i\n", i);
77 : 0 : return OPAL_RESOURCE;
78 : : }
79 : 25 : if (!s) {
80 : 0 : prerror("FLASH: flash subpartition zero size: %i\n", i);
81 : 0 : return OPAL_RESOURCE;
82 : : }
83 : 25 : if (o < FLASH_SUBPART_HEADER_SIZE) {
84 : 0 : prerror("FLASH: flash subpartition offset too small: "
85 : : "%i\n", i);
86 : 0 : return OPAL_RESOURCE;
87 : : }
88 : : /*
89 : : * Subpartitions content are different, but multiple toc entries
90 : : * may point to the same subpartition.
91 : : */
92 : 25 : if (ALIGN_UP(o + s, FLASH_SUBPART_HEADER_SIZE) > part_actual)
93 : 5 : part_actual = ALIGN_UP(o + s, FLASH_SUBPART_HEADER_SIZE);
94 : :
95 : 25 : if (ec == subid) {
96 : 5 : if (offset)
97 : 5 : *offset += o;
98 : 5 : if (size)
99 : 5 : *size = s;
100 : 5 : subpart_found = true;
101 : : }
102 : : }
103 : 5 : if (!subpart_found && (offset || size)) {
104 : 0 : prerror("FLASH: flash subpartition not found.\n");
105 : 0 : return OPAL_RESOURCE;
106 : : }
107 : 5 : if (part_actualp)
108 : 5 : *part_actualp = part_actual;
109 : 5 : return OPAL_SUCCESS;
110 : : }
|