1 /* 2 * Copyright (C) 2011 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <errno.h> 18 #include <fcntl.h> 19 #include <getopt.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <sys/stat.h> 24 #include <sys/wait.h> 25 #include <unistd.h> 26 #include <stdint.h> 27 28 #include "fw_version_check.h" 29 30 #define DEVICE_NAME "/sys/kernel/fw_update/fw_info/fw_version" 31 #define FIP_PATTERN 0x50494624 32 #define SCU_IPC_VERSION_LEN_LONG 32 33 #define READ_SZ 256 34 35 struct fip_version_block { 36 uint16_t minor; 37 uint16_t major; 38 uint8_t checksum; 39 uint8_t reserved8; 40 uint16_t reserved16; 41 }; 42 43 struct fip_version_block_chxx { 44 uint16_t minor; 45 uint16_t major; 46 uint8_t checksum; 47 uint8_t reserved8; 48 uint16_t reserved16; 49 uint16_t size; 50 uint16_t dest; 51 }; 52 53 struct FIP_header { 54 uint32_t FIP_SIG; 55 struct fip_version_block umip_rev; 56 struct fip_version_block spat_rev; 57 struct fip_version_block spct_rev; 58 struct fip_version_block rpch_rev; 59 struct fip_version_block ch00_rev; 60 struct fip_version_block mipd_rev; 61 struct fip_version_block mipn_rev; 62 struct fip_version_block scuc_rev; 63 struct fip_version_block hvm_rev; 64 struct fip_version_block mia_rev; 65 struct fip_version_block ia32_rev; 66 struct fip_version_block oem_rev; 67 struct fip_version_block ved_rev; 68 struct fip_version_block vec_rev; 69 struct fip_version_block mos_rev; 70 struct fip_version_block pos_rev; 71 struct fip_version_block cos_rev; 72 struct fip_version_block_chxx ch01_rev; 73 struct fip_version_block_chxx ch02_rev; 74 struct fip_version_block_chxx ch03_rev; 75 struct fip_version_block_chxx ch04_rev; 76 struct fip_version_block_chxx ch05_rev; 77 struct fip_version_block_chxx ch06_rev; 78 struct fip_version_block_chxx ch07_rev; 79 struct fip_version_block_chxx ch08_rev; 80 struct fip_version_block_chxx ch09_rev; 81 struct fip_version_block_chxx ch10_rev; 82 struct fip_version_block_chxx ch11_rev; 83 struct fip_version_block_chxx ch12_rev; 84 struct fip_version_block_chxx ch13_rev; 85 struct fip_version_block_chxx ch14_rev; 86 struct fip_version_block_chxx ch15_rev; 87 struct fip_version_block dnx_rev; 88 struct fip_version_block reserved0_rev; 89 struct fip_version_block reserved1_rev; 90 struct fip_version_block ifwi_rev; 91 }; 92 93 static int read_fw_revision(unsigned int *fw_revision, int len) 94 { 95 int i, fw_info, ret; 96 const char *sep = " "; 97 char *p, *save; 98 char buf[READ_SZ]; 99 100 fw_info = open(DEVICE_NAME, O_RDONLY); 101 if (fw_info < 0) { 102 fprintf(stderr, "failed to open %s ", DEVICE_NAME); 103 return fw_info; 104 } 105 106 ret = read(fw_info, buf, READ_SZ - 1); 107 if (ret < 0) { 108 fprintf(stderr, "failed to read fw_revision, ret = %d\n", ret); 109 goto err; 110 } 111 112 buf[ret] = 0; 113 p = strtok_r(buf, sep, &save); 114 for (i = 0; p && i < len; i++) { 115 ret = sscanf(p, "%x", &fw_revision[i]); 116 if (ret != 1) { 117 fprintf(stderr, "failed to parse fw_revision, ret = %d\n", ret); 118 goto err; 119 } 120 p = strtok_r(NULL, sep, &save); 121 } 122 ret = 0; 123 124 err: 125 close(fw_info); 126 return ret; 127 } 128 129 /* Bytes in scu_ipc_version after the ioctl(): 130 131 * 00 SCU Boot Strap Firmware Minor Revision Low 132 * 01 SCU Boot Strap Firmware Minor Revision High 133 * 02 SCU Boot Strap Firmware Major Revision Low 134 * 03 SCU Boot Strap Firmware Major Revision High 135 136 * 04 SCU Firmware Minor Revision Low 137 * 05 SCU Firmware Minor Revision High 138 * 06 SCU Firmware Major Revision Low 139 * 07 SCU Firmware Major Revision High 140 141 * 08 IA Firmware Minor Revision Low 142 * 09 IA Firmware Minor Revision High 143 * 10 IA Firmware Major Revision Low 144 * 11 IA Firmware Major Revision High 145 146 * 12 Validation Hooks Firmware Minor Revision Low 147 * 13 Validation Hooks Firmware Minor Revision High 148 * 14 Validation Hooks Firmware Major Revision Low 149 * 15 Validation Hooks Firmware Major Revision High 150 151 * 16 IFWI Firmware Minor Revision Low 152 * 17 IFWI Firmware Minor Revision High 153 * 18 IFWI Firmware Major Revision Low 154 * 19 IFWI Firmware Major Revision High 155 156 * 20 Chaabi Firmware Minor Revision Low 157 * 21 Chaabi Firmware Minor Revision High 158 * 22 Chaabi Firmware Major Revision Low 159 * 23 Chaabi Firmware Major Revision High 160 161 * 24 mIA Firmware Minor Revision Low 162 * 25 mIA Firmware Minor Revision High 163 * 26 mIA Firmware Major Revision Low 164 * 27 mIA Firmware Major Revision High 165 166 */ 167 int get_current_fw_rev(struct firmware_versions *v) 168 { 169 int ret; 170 unsigned int fw_revision[SCU_IPC_VERSION_LEN_LONG] = { 0 }; 171 172 ret = read_fw_revision(fw_revision, SCU_IPC_VERSION_LEN_LONG); 173 if (ret) 174 return ret; 175 176 v->scubootstrap.minor = fw_revision[1] << 8 | fw_revision[0]; 177 v->scubootstrap.major = fw_revision[3] << 8 | fw_revision[2]; 178 v->scu.minor = fw_revision[5] << 8 | fw_revision[4]; 179 v->scu.major = fw_revision[7] << 8 | fw_revision[6]; 180 v->ia32.minor = fw_revision[9] << 8 | fw_revision[8]; 181 v->ia32.major = fw_revision[11] << 8 | fw_revision[10]; 182 v->valhooks.minor = fw_revision[13] << 8 | fw_revision[12]; 183 v->valhooks.major = fw_revision[15] << 8 | fw_revision[14]; 184 v->ifwi.minor = fw_revision[17] << 8 | fw_revision[16]; 185 v->ifwi.major = fw_revision[19] << 8 | fw_revision[18]; 186 v->chaabi.minor = fw_revision[21] << 8 | fw_revision[20]; 187 v->chaabi.major = fw_revision[23] << 8 | fw_revision[22]; 188 v->mia.minor = fw_revision[25] << 8 | fw_revision[24]; 189 v->mia.major = fw_revision[27] << 8 | fw_revision[26]; 190 191 return ret; 192 } 193 194 int get_image_fw_rev(void *data, unsigned sz, struct firmware_versions *v) 195 { 196 struct FIP_header fip; 197 unsigned char *databytes = (unsigned char *)data; 198 int magic; 199 int magic_found = 0; 200 201 if (v == NULL) { 202 fprintf(stderr, "Null pointer !\n"); 203 return -1; 204 } else 205 memset((void *)v, 0, sizeof(struct firmware_versions)); 206 207 while (sz >= sizeof(fip)) { 208 209 /* Scan for the FIP magic */ 210 while (sz >= sizeof(fip)) { 211 memcpy(&magic, databytes, sizeof(magic)); 212 if (magic == FIP_PATTERN) { 213 magic_found = 1; 214 break; 215 } 216 databytes += sizeof(magic); 217 sz -= sizeof(magic); 218 } 219 220 if (!magic_found) { 221 fprintf(stderr, "Couldn't find FIP magic in image!\n"); 222 return -1; 223 } 224 if (sz < sizeof(fip)) { 225 break; 226 } 227 228 memcpy(&fip, databytes, sizeof(fip)); 229 230 /* not available in ifwi file */ 231 v->scubootstrap.minor = 0; 232 v->scubootstrap.major = 0; 233 234 /* don't update if null */ 235 if (fip.scuc_rev.minor != 0) 236 v->scu.minor = fip.scuc_rev.minor; 237 if (fip.scuc_rev.major != 0) 238 v->scu.major = fip.scuc_rev.major; 239 if (fip.ia32_rev.minor != 0) 240 v->ia32.minor = fip.ia32_rev.minor; 241 if (fip.ia32_rev.major != 0) 242 v->ia32.major = fip.ia32_rev.major; 243 if (fip.oem_rev.minor != 0) 244 v->valhooks.minor = fip.oem_rev.minor; 245 if (fip.oem_rev.major != 0) 246 v->valhooks.major = fip.oem_rev.major; 247 if (fip.ifwi_rev.minor != 0) 248 v->ifwi.minor = fip.ifwi_rev.minor; 249 if (fip.ifwi_rev.major != 0) 250 v->ifwi.major = fip.ifwi_rev.major; 251 if (fip.ch00_rev.minor != 0) 252 v->chaabi.minor = fip.ch00_rev.minor; 253 if (fip.ch00_rev.major != 0) 254 v->chaabi.major = fip.ch00_rev.major; 255 if (fip.mia_rev.minor != 0) 256 v->mia.minor = fip.mia_rev.minor; 257 if (fip.mia_rev.major != 0) 258 v->mia.major = fip.mia_rev.major; 259 260 databytes += sizeof(magic); 261 sz -= sizeof(magic); 262 } 263 264 return 0; 265 } 266