2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * CDDL HEADER START
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * The contents of this file are subject to the terms of the
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Common Development and Distribution License (the "License").
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * You may not use this file except in compliance with the License.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * See the License for the specific language governing permissions
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * and limitations under the License.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * When distributing Covered Code, include this CDDL HEADER in each
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * If applicable, add the following below this CDDL HEADER, with the
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * fields enclosed by brackets "[]" replaced with your own identifying
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * information: Portions Copyright [yyyy] [name of copyright owner]
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * CDDL HEADER END
0ba6f73dcd1c9160a44b2872ed0e0d81b51d168fMark Johnson * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Use is subject to license terms.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrymstatic const char ucode_dev[] = "/dev/" UCODE_DRIVER_NAME;
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrymstatic char ucode_vendor_str[UCODE_MAX_VENDORS_NAME_LEN];
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrymstatic char ucode_install_path[] = UCODE_INSTALL_PATH;
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonstatic int ucode_convert_amd(const char *, uint8_t *, size_t);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonstatic int ucode_convert_intel(const char *, uint8_t *, size_t);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonstatic ucode_errno_t ucode_gen_files_amd(uint8_t *, int, char *);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonstatic ucode_errno_t ucode_gen_files_intel(uint8_t *, int, char *);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson { ucode_convert_intel, ucode_gen_files_intel, ucode_validate_intel },
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson { ucode_convert_amd, ucode_gen_files_amd, ucode_validate_amd },
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym gettext("\t\t Shows running microcode version.\n\n"));
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson (void) fprintf(stderr, "\t%s -u microcode-file\n", cmdname);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym (void) fprintf(stderr, gettext("\t\t Updates microcode to the "
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym "latest matching version found in\n"
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson "\t\t microcode-file.\n\n"));
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson (void) fprintf(stderr, "\t%s -i [-R path] microcode-file\n", cmdname);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym (void) fprintf(stderr, gettext("\t\t Installs microcode to be "
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson "used for subsequent boots.\n\n"));
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson (void) fprintf(stderr, gettext("Microcode file name must start "
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson "with vendor name, such as \"intel\" or \"amd\".\n\n"));
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym (void) fprintf(stderr, "%s: %s: %s\n", cmdname, str,
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym#define LINESIZE 120 /* copyright line sometimes is longer than 80 */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Convert text format microcode release into binary format.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Return the number of characters read.
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonucode_convert_amd(const char *infile, uint8_t *buf, size_t size)
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson if (infile == NULL || buf == NULL || size == 0)
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonucode_convert_intel(const char *infile, uint8_t *buf, size_t size)
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (0);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (0);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Check to see if we are processing a binary file */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Skip blank lines */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Skip lines with all spaces or tabs */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Text file. Skip comments. */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * If we get here, we are processing a text format file
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * where "count" is used to count the number of integers
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * read. Convert it to number of characters read.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (count * sizeof (int));
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Returns 0 if no need to update the link; -1 otherwise
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonucode_should_update_intel(char *filename, uint32_t new_rev)
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * If the file or link already exists, check to see if
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * it is necessary to update it.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (-1);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (-1);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (0);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (-1);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Generate microcode binary files. Must be called after ucode_validate().
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonucode_gen_files_amd(uint8_t *buf, int size, char *path)
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson /* LINTED: pointer alignment */
0ba6f73dcd1c9160a44b2872ed0e0d81b51d168fMark Johnson /* write container file */
08d2fdc210e92c7a249e69a795663019da6f23caMark Johnson (void) snprintf(common_path, PATH_MAX, "%s/%s", path, "container");
08d2fdc210e92c7a249e69a795663019da6f23caMark Johnson fd = open(common_path, O_WRONLY | O_CREAT | O_TRUNC,
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson /* skip over magic number & equivalence table header */
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson /* equivalence table uses special name */
08d2fdc210e92c7a249e69a795663019da6f23caMark Johnson (void) snprintf(common_path, PATH_MAX, "%s/%s", path,
08d2fdc210e92c7a249e69a795663019da6f23caMark Johnson "equivalence-table");
08d2fdc210e92c7a249e69a795663019da6f23caMark Johnson fd = open(common_path, O_WRONLY | O_CREAT | O_TRUNC,
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson /* construct name from header information */
08d2fdc210e92c7a249e69a795663019da6f23caMark Johnson (void) snprintf(common_path, PATH_MAX, "%s/%04X-%02X", path,
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnsonucode_gen_files_intel(uint8_t *buf, int size, char *path)
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym (void) snprintf(common_path, PATH_MAX, "%s/%s", path,
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym if (mkdirp(common_path, 0755) == -1 && errno != EEXIST) {
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson uhp = (ucode_header_intel_t *)(intptr_t)curbuf;
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson total_size = UCODE_TOTAL_SIZE_INTEL(uhp->uh_total_size);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson body_size = UCODE_BODY_SIZE_INTEL(uhp->uh_body_size);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym (void) snprintf(firstname, PATH_MAX, "%s/%08X-%02X",
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym common_path, uhp->uh_signature, uhp->uh_proc_flags);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson if (ucode_should_update_intel(firstname, uhp->uh_rev) != 0) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Remove the existing one first */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym if ((fd = open(firstname, O_WRONLY | O_CREAT | O_TRUNC,
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Only 1 byte of the proc_flags field is used, therefore
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * we only need to match 8 potential platform ids.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym for (i = 0; i < 8; i++) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym dprintf("proc_flags = %x, platid = %x, name = %s\n",
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson if (ucode_should_update_intel(name, uhp->uh_rev) != 0) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Remove the existing one first */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Check to see if there is extended signature table */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* There is extended signature table. More processing. */
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson extp = (ucode_ext_table_intel_t *)(uintptr_t)&curbuf[offset];
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson ucode_ext_sig_intel_t *uesp = &extp->uet_ext_sig[i];
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym for (j = 0; j < 8; j++) {
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson if (ucode_should_update_intel(name, uhp->uh_rev)
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym /* Remove the existing one first */
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Remove files with no links to them. These are probably
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * obsolete microcode files.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Returns 0 on success, 2 on usage error, and 3 on operation error.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym while ((c = getopt(argc, argv, "idhuvVR:")) != EOF) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym switch (c) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (0);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (2);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym (void) fprintf(stderr, gettext("%s: options -v, -i and -u "
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (2);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (2);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * Convert from text format to binary format
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym if ((action & UCODE_OPT_INSTALL) || (action & UCODE_OPT_UPDATE)) {
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson for (i = 0; ucode_vendors[i].filestr != NULL; i++) {
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson dprintf("i = %d, filestr = %s, filename = %s\n",
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson ucode_size = ucode->convert(filename, buf, filestat.st_size);
adc586debf12d2592024c0b8b9e44ffa104f858cMark Johnson if ((rc = ucode->validate(buf, ucode_size)) != EM_OK) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * For the install option, the microcode file must start with
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * "intel" for Intel microcode, and "amd" for AMD microcode.
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym * If no path is provided by the -R option, put the files in
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym for (i = 0; i < cpuid_max; i++)
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym for (i = 0; i < cpuid_max; i++) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym } else if (rc == EM_NOMATCH || rc == EM_HIGHERREV) {
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (3);
2449e17f82f6097fd2c665b64723e31ceecbeca6sherrym return (0);