示例#1
0
/****************************************************************************
 * get_cmos_checksum_info
 *
 * Get layout information for CMOS checksum.
 ****************************************************************************/
static void get_cmos_checksum_info(void)
{
	const cmos_entry_t *e;
	struct cmos_checksum *checksum;
	cmos_checksum_layout_t layout;
	unsigned index, index2;

	checksum = (struct cmos_checksum *)next_cmos_rec((const struct lb_record *)first_cmos_table_enum(), LB_TAG_OPTION_CHECKSUM);

	if (checksum != NULL) {	/* We are lucky.  The coreboot table hints us to the checksum.
				 * We might have to check the type field here though.
				 */
		layout.summed_area_start = checksum->range_start;
		layout.summed_area_end = checksum->range_end;
		layout.checksum_at = checksum->location;
		try_convert_checksum_layout(&layout);
		cmos_checksum_start = layout.summed_area_start;
		cmos_checksum_end = layout.summed_area_end;
		cmos_checksum_index = layout.checksum_at;
		return;
	}

	if ((e = find_cmos_entry(checksum_param_name)) == NULL)
		return;

	/* If we get here, we are unlucky.  The CMOS option table contains the
	 * location of the CMOS checksum.  However, there is no information
	 * regarding which bytes of the CMOS area the checksum is computed over.
	 * Thus we have to hope our presets will be fine.
	 */

	if (e->bit % 8) {
		fprintf(stderr,
			"%s: Error: CMOS checksum is not byte-aligned.\n",
			prog_name);
		exit(1);
	}

	index = e->bit / 8;
	index2 = index + 1;	/* The CMOS checksum occupies 16 bits. */

	if (verify_cmos_byte_index(index) || verify_cmos_byte_index(index2)) {
		fprintf(stderr,
			"%s: Error: CMOS checksum location out of range.\n",
			prog_name);
		exit(1);
	}

	if (((index >= cmos_checksum_start) && (index <= cmos_checksum_end)) ||
	    (((index2) >= cmos_checksum_start)
	     && ((index2) <= cmos_checksum_end))) {
		fprintf(stderr,
			"%s: Error: CMOS checksum overlaps checksummed area.\n",
			prog_name);
		exit(1);
	}

	cmos_checksum_index = index;
}
示例#2
0
/****************************************************************************
 * list_one_param
 *
 * Attempt to list one CMOS parameter given by 'name'.  'show_name' is a
 * boolean value indicating whether the parameter name should be displayed
 * along with its value.  Return 1 if error was encountered.  Else return OK.
 ****************************************************************************/
static int list_one_param(const char name[], int show_name)
{
	const cmos_entry_t *e;

	if (is_checksum_name(name) || ((e = find_cmos_entry(name)) == NULL)) {
		fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name,
			name);
		exit(1);
	}

	if (e->config == CMOS_ENTRY_RESERVED) {
		fprintf(stderr, "%s: Parameter %s is reserved.\n", prog_name,
			name);
		exit(1);
	}

	return (list_cmos_entry(e, show_name) != 0);
}
示例#3
0
/****************************************************************************
 * list_param_enums
 *
 * List all possible values for CMOS parameter given by 'name'.
 ****************************************************************************/
static void list_param_enums(const char name[])
{
	const cmos_entry_t *e;
	const cmos_enum_t *p;

	if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) {
		fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name,
			name);
		exit(1);
	}

	switch (e->config) {
	case CMOS_ENTRY_ENUM:
		for (p = first_cmos_enum_id(e->config_id);
		     p != NULL; p = next_cmos_enum_id(p))
			printf("%s\n", p->text);

		break;

	case CMOS_ENTRY_HEX:
		printf("Parameter %s requires a %u-bit unsigned integer.\n",
		       name, e->length);
		break;

	case CMOS_ENTRY_STRING:
		printf("Parameter %s requires a %u-byte string.\n", name,
		       e->length / 8);
		break;

	case CMOS_ENTRY_RESERVED:
		printf("Parameter %s is reserved.\n", name);
		break;

	default:
		BUG();
	}
}
示例#4
0
/****************************************************************************
 * process_input_file
 *
 * Read the contents of file 'f' and return a pointer to a list of pending
 * write operations.  Perform sanity checking on all write operations and
 * exit with an error message if there is a problem.
 ****************************************************************************/
cmos_write_t *process_input_file(FILE * f)
{
	static const int LINE_BUF_SIZE = 256;
	static const size_t N_MATCHES = 4;
	char line[LINE_BUF_SIZE];
	const char *name, *value;
	cmos_write_t *list, *item, **p;
	regex_t blank_or_comment, assignment;
	regmatch_t match[N_MATCHES];
	const cmos_entry_t *e;

	list = NULL;
	p = &list;

	compile_reg_expr(REG_EXTENDED | REG_NEWLINE, blank_or_comment_regex, &blank_or_comment);
	compile_reg_expr(REG_EXTENDED | REG_NEWLINE, assignment_regex, &assignment);

	/* each iteration processes one line from input file */
	for (line_num = 1; get_input_file_line(f, line, LINE_BUF_SIZE) == OK; line_num++) {	/* skip comments and blank lines */
		if (!regexec(&blank_or_comment, line, 0, NULL, 0))
			continue;

		/* Is this a valid assignment line?  If not, then it's a syntax
		 * error.
		 */
		if (regexec(&assignment, line, N_MATCHES, match, 0)) {
			fprintf(stderr,
				"%s: Syntax error on line %d of input file.\n",
				prog_name, line_num);
			exit(1);
		}

		/* OK, we found an assignment.  Break the line into substrings
		 * representing the lefthand and righthand sides of the assignment.
		 */
		line[match[1].rm_eo] = '\0';
		line[match[2].rm_eo] = '\0';
		name = &line[match[1].rm_so];
		value = &line[match[2].rm_so];

		/* now look up the coreboot parameter name */
		if (is_checksum_name(name)
		    || (e = find_cmos_entry(name)) == NULL) {
			fprintf(stderr,
				"%s: Error on line %d of input file: CMOS parameter "
				"%s not found.\n", prog_name, line_num, name);
			exit(1);
		}

		/* At this point, we figure out what numeric value needs to be written
		 * to which location.  At the same time, we perform sanity checking on
		 * the write operation.
		 */

		if ((item = (cmos_write_t *) malloc(sizeof(*item))) == NULL)
			out_of_memory();

		item->bit = e->bit;
		item->length = e->length;
		item->config = e->config;
		item->value = try_prepare_cmos_write(e, value);

		/* Append write operation to pending write list. */
		item->next = NULL;
		*p = item;
		p = &item->next;
	}

	regfree(&blank_or_comment);
	regfree(&assignment);
	return list;
}
示例#5
0
/****************************************************************************
 * set_one_param
 *
 * Set the CMOS parameter given by 'name' to 'value'.  The 'name' parameter
 * is case-sensitive.  If we are setting an enum parameter, then 'value' is
 * interpreted as a case-sensitive string that must match the option name
 * exactly.  If we are setting a 'hex' parameter, then 'value' is treated as
 * a string representation of an unsigned integer that may be specified in
 * decimal, hex, or octal.
 ****************************************************************************/
static void set_one_param(const char name[], const char value[])
{
	const cmos_entry_t *e;
	unsigned long long n;

	if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) {
		fprintf(stderr, "%s: CMOS parameter %s not found.", prog_name,
			name);
		exit(1);
	}

	switch (prepare_cmos_write(e, value, &n)) {
	case OK:
		break;

	case CMOS_OP_BAD_ENUM_VALUE:
		fprintf(stderr, "%s: Bad value for parameter %s.", prog_name,
			name);
		goto fail;

	case CMOS_OP_NEGATIVE_INT:
		fprintf(stderr,
			"%s: This program does not support assignment of negative "
			"numbers to coreboot parameters.", prog_name);
		goto fail;

	case CMOS_OP_INVALID_INT:
		fprintf(stderr, "%s: %s is not a valid integer.", prog_name,
			value);
		goto fail;

	case CMOS_OP_RESERVED:
		fprintf(stderr,
			"%s: Can not modify reserved coreboot parameter %s.",
			prog_name, name);
		goto fail;

	case CMOS_OP_VALUE_TOO_WIDE:
		fprintf(stderr,
			"%s: Can not write value %s to CMOS parameter %s that is "
			"only %d bits wide.", prog_name, value, name,
			e->length);
		goto fail;

	case CMOS_OP_NO_MATCHING_ENUM:
		fprintf(stderr,
			"%s: coreboot parameter %s has no matching enums.",
			prog_name, name);
		goto fail;

	case CMOS_AREA_OUT_OF_RANGE:
		fprintf(stderr,
			"%s: The CMOS area specified by the layout info for "
			"coreboot parameter %s is out of range.", prog_name,
			name);
		goto fail;

	case CMOS_AREA_OVERLAPS_RTC:
		fprintf(stderr,
			"%s: The CMOS area specified by the layout info for "
			"coreboot parameter %s overlaps the realtime clock area.",
			prog_name, name);
		goto fail;

	case CMOS_AREA_TOO_WIDE:
		fprintf(stderr,
			"%s: The CMOS area specified by the layout info for "
			"coreboot parameter %s is too wide.", prog_name, name);
		goto fail;

	default:
		fprintf(stderr,
			"%s: Unknown error encountered while attempting to modify "
			"coreboot parameter %s.", prog_name, name);
		goto fail;
	}

	/* write the value to nonvolatile RAM */
	set_iopl(3);
	cmos_write(e, n);
	cmos_checksum_write(cmos_checksum_compute());
	set_iopl(0);
	return;

      fail:
	fprintf(stderr, "  CMOS write not performed.\n");
	exit(1);
}