at v206 3.2 kB view raw
1/* 2 * Convert Intel microcode.dat into a single binary microcode.bin file 3 * 4 * Based on code by Kay Sievers <kay.sievers@vrfy.org> 5 * Changed to create a single file by Thomas Bächler <thomas@archlinux.org> 6 */ 7 8 9#ifndef _GNU_SOURCE 10# define _GNU_SOURCE 1 11#endif 12 13#include <stdio.h> 14#include <unistd.h> 15#include <stdlib.h> 16#include <string.h> 17#include <time.h> 18#include <limits.h> 19#include <stdbool.h> 20#include <inttypes.h> 21#include <fcntl.h> 22#include <errno.h> 23#include <sys/stat.h> 24 25struct microcode_header_intel { 26 unsigned int hdrver; 27 unsigned int rev; 28 unsigned int date; 29 unsigned int sig; 30 unsigned int cksum; 31 unsigned int ldrver; 32 unsigned int pf; 33 unsigned int datasize; 34 unsigned int totalsize; 35 unsigned int reserved[3]; 36}; 37 38union mcbuf { 39 struct microcode_header_intel hdr; 40 unsigned int i[0]; 41 char c[0]; 42}; 43 44int main(int argc, char *argv[]) 45{ 46 const char *filename = "/lib/firmware/microcode.dat"; 47 FILE *f; 48 char line[LINE_MAX]; 49 char buf[4000000]; 50 union mcbuf *mc; 51 size_t bufsize, count, start; 52 int rc = EXIT_SUCCESS; 53 54 if (argv[1] != NULL) 55 filename = argv[1]; 56 57 count = 0; 58 mc = (union mcbuf *) buf; 59 f = fopen(filename, "re"); 60 if (f == NULL) { 61 printf("open %s: %m\n", filename); 62 rc = EXIT_FAILURE; 63 goto out; 64 } 65 66 while (fgets(line, sizeof(line), f) != NULL) { 67 if (sscanf(line, "%x, %x, %x, %x", 68 &mc->i[count], 69 &mc->i[count + 1], 70 &mc->i[count + 2], 71 &mc->i[count + 3]) != 4) 72 continue; 73 count += 4; 74 } 75 fclose(f); 76 77 bufsize = count * sizeof(int); 78 printf("%s: %lu(%luk) bytes, %zu integers\n", 79 filename, 80 bufsize, 81 bufsize / 1024, 82 count); 83 84 if (bufsize < sizeof(struct microcode_header_intel)) 85 goto out; 86 87 f = fopen("microcode.bin", "we"); 88 if (f == NULL) { 89 printf("open microcode.bin: %m\n"); 90 rc = EXIT_FAILURE; 91 goto out; 92 } 93 94 start = 0; 95 for (;;) { 96 size_t size; 97 unsigned int family, model, stepping; 98 unsigned int year, month, day; 99 100 mc = (union mcbuf *) &buf[start]; 101 102 if (mc->hdr.totalsize) 103 size = mc->hdr.totalsize; 104 else 105 size = 2000 + sizeof(struct microcode_header_intel); 106 107 if (mc->hdr.ldrver != 1 || mc->hdr.hdrver != 1) { 108 printf("unknown version/format:\n"); 109 rc = EXIT_FAILURE; 110 break; 111 } 112 113 /* 114 * 0- 3 stepping 115 * 4- 7 model 116 * 8-11 family 117 * 12-13 type 118 * 16-19 extended model 119 * 20-27 extended family 120 */ 121 family = (mc->hdr.sig >> 8) & 0xf; 122 if (family == 0xf) 123 family += (mc->hdr.sig >> 20) & 0xff; 124 model = (mc->hdr.sig >> 4) & 0x0f; 125 if (family == 0x06) 126 model += ((mc->hdr.sig >> 16) & 0x0f) << 4; 127 stepping = mc->hdr.sig & 0x0f; 128 129 year = mc->hdr.date & 0xffff; 130 month = mc->hdr.date >> 24; 131 day = (mc->hdr.date >> 16) & 0xff; 132 133 printf("\n"); 134 printf("signature: 0x%02x\n", mc->hdr.sig); 135 printf("flags: 0x%02x\n", mc->hdr.pf); 136 printf("revision: 0x%02x\n", mc->hdr.rev); 137 printf("date: %04x-%02x-%02x\n", year, month, day); 138 printf("size: %zu\n", size); 139 140 if (fwrite(mc, size, 1, f) != 1) { 141 printf("write microcode.bin: %m\n"); 142 rc = EXIT_FAILURE; 143 goto out; 144 } 145 146 start += size; 147 if (start >= bufsize) 148 break; 149 } 150 fclose(f); 151 printf("\n"); 152out: 153 return rc; 154}