Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * Parse VERSION partition, add to device tree
4 : : *
5 : : * Copyright 2013-2018 IBM Corp.
6 : : */
7 : :
8 : : #include <skiboot.h>
9 : : #include <device.h>
10 : : #include <opal.h>
11 : : #include <libstb/secureboot.h>
12 : : #include <libstb/trustedboot.h>
13 : :
14 : : /* ibm,firmware-versions support */
15 : : static char *version_buf;
16 : : static size_t version_buf_size = 0x2000;
17 : :
18 : 96 : static void __flash_dt_add_fw_version(struct dt_node *fw_version, char* data)
19 : : {
20 : : static bool first = true;
21 : : char *prop;
22 : : int version_len, i;
23 : 96 : int len = strlen(data);
24 : : const char *skiboot_version;
25 : 96 : const char * version_str[] = {"open-power", "buildroot", "skiboot",
26 : : "hostboot-binaries", "hostboot", "linux",
27 : : "petitboot", "occ", "capp-ucode", "sbe",
28 : : "machine-xml", "hcode"};
29 : :
30 : 96 : if (first) {
31 : 12 : first = false;
32 : :
33 : : /* Increment past "key-" */
34 : 12 : if (memcmp(data, "open-power", strlen("open-power")) == 0)
35 : 10 : prop = data + strlen("open-power");
36 : : else
37 : 2 : prop = strchr(data, '-');
38 : 12 : if (!prop) {
39 : 1 : prlog(PR_DEBUG,
40 : : "FLASH: Invalid fw version format (%s)\n", data);
41 : 12 : return;
42 : : }
43 : 11 : prop++;
44 : :
45 : 11 : dt_add_property_string(fw_version, "version", prop);
46 : 11 : return;
47 : : }
48 : :
49 : : /*
50 : : * PNOR version strings are not easily consumable. Split them into
51 : : * property, value.
52 : : *
53 : : * Example input from PNOR :
54 : : * "open-power-firestone-v1.8"
55 : : * "linux-4.4.6-openpower1-8420e0f"
56 : : *
57 : : * Desired output in device tree:
58 : : * open-power = "firestone-v1.8";
59 : : * linux = "4.4.6-openpower1-8420e0f";
60 : : */
61 : 1092 : for(i = 0; i < ARRAY_SIZE(version_str); i++)
62 : : {
63 : 1008 : version_len = strlen(version_str[i]);
64 : 1008 : if (len < version_len)
65 : 39 : continue;
66 : :
67 : 969 : if (memcmp(data, version_str[i], version_len) != 0)
68 : 887 : continue;
69 : :
70 : : /* Found a match, add property */
71 : 82 : if (dt_find_property(fw_version, version_str[i]))
72 : 6 : continue;
73 : :
74 : : /* Increment past "key-" */
75 : 76 : prop = data + version_len + 1;
76 : 76 : dt_add_property_string(fw_version, version_str[i], prop);
77 : :
78 : : /* Sanity check against what Skiboot thinks its version is. */
79 : 76 : if (strncmp(version_str[i], "skiboot",
80 : : strlen("skiboot")) == 0) {
81 : : /*
82 : : * If Skiboot was built with Buildroot its version may
83 : : * include a 'skiboot-' prefix; ignore it.
84 : : */
85 : : if (strncmp(version, "skiboot-",
86 : : strlen("skiboot-")) == 0)
87 : : skiboot_version = version + strlen("skiboot-");
88 : : else
89 : 9 : skiboot_version = version;
90 : 9 : if (strncmp(prop, skiboot_version,
91 : : strlen(skiboot_version)) != 0)
92 : 9 : prlog(PR_WARNING, "WARNING! Skiboot version does not match VERSION partition!\n");
93 : : }
94 : : }
95 : : }
96 : :
97 : 13 : void flash_dt_add_fw_version(void)
98 : : {
99 : : uint8_t version_data[80];
100 : : int rc;
101 : 13 : int numbytes = 0, i = 0;
102 : : struct dt_node *fw_version;
103 : :
104 : 13 : if (version_buf == NULL)
105 : 0 : return;
106 : :
107 : 13 : rc = wait_for_resource_loaded(RESOURCE_ID_VERSION, RESOURCE_SUBID_NONE);
108 : 13 : if (rc != OPAL_SUCCESS) {
109 : 0 : prlog(PR_WARNING, "FLASH: Failed to load VERSION data\n");
110 : 0 : free(version_buf);
111 : 0 : return;
112 : : }
113 : :
114 : 13 : fw_version = dt_new(dt_root, "ibm,firmware-versions");
115 : 13 : assert(fw_version);
116 : :
117 : 13 : if (stb_is_container(version_buf, version_buf_size))
118 : 0 : numbytes += SECURE_BOOT_HEADERS_SIZE;
119 : 2520 : for ( ; (numbytes < version_buf_size) && version_buf[numbytes]; numbytes++) {
120 : 2508 : if (version_buf[numbytes] == '\n') {
121 : 96 : version_data[i] = '\0';
122 : 96 : __flash_dt_add_fw_version(fw_version, version_data);
123 : 96 : memset(version_data, 0, sizeof(version_data));
124 : 96 : i = 0;
125 : 96 : continue;
126 : 2412 : } else if (version_buf[numbytes] == '\t') {
127 : 85 : continue; /* skip tabs */
128 : : }
129 : :
130 : 2327 : version_data[i++] = version_buf[numbytes];
131 : 2327 : if (i == sizeof(version_data)) {
132 : 1 : prlog(PR_WARNING, "VERSION item >%lu chars, skipping\n",
133 : : sizeof(version_data));
134 : 1 : break;
135 : : }
136 : : }
137 : :
138 : 13 : free(version_buf);
139 : : }
140 : :
141 : 26 : void flash_fw_version_preload(void)
142 : : {
143 : : int rc;
144 : :
145 : 26 : if (proc_gen < proc_gen_p9)
146 : 13 : return;
147 : :
148 : 13 : prlog(PR_INFO, "FLASH: Loading VERSION section\n");
149 : :
150 : 13 : version_buf = malloc(version_buf_size);
151 : 13 : if (!version_buf) {
152 : 0 : prlog(PR_WARNING, "FLASH: Failed to allocate memory\n");
153 : 0 : return;
154 : : }
155 : :
156 : 13 : rc = start_preload_resource(RESOURCE_ID_VERSION, RESOURCE_SUBID_NONE,
157 : : version_buf, &version_buf_size);
158 : 13 : if (rc != OPAL_SUCCESS) {
159 : 0 : prlog(PR_WARNING,
160 : : "FLASH: Failed to start loading VERSION data\n");
161 : 0 : free(version_buf);
162 : 0 : version_buf = NULL;
163 : : }
164 : : }
|