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 : : }