config.c

来自「EFI(Extensible Firmware Interface)是下一代BI」· C语言 代码 · 共 1,131 行 · 第 1/2 页

C
1,131
字号
{	CHAR16 numstr[MAX_STRING];	CHAR16 *str;	token_t tok;	UINTN *buf;	UINTN tmp;	/*	 * match the '=' sign	 */	tok = get_token(numstr, MAX_STRING);	if (tok != TOK_EQUAL) {		config_error(L"Option %s expects an equal signal + value", p->name);		return -1;	}	/*	 * now get the value	 * XXX: = lexer should return TOK_NUM (and we'd be done)	 */	tok = get_token(numstr, MAX_STRING);	if (tok != TOK_STR) {		config_error(L"Option %s expects a value", p->name);		return -1;	}	str = numstr;	/*	 * if there is a customized way of doing the operation	 * do it and bypass generic	 */	if (p->action) return p->action(p, str);	/*	 * no field to update	 */	if (p->data == NULL) return 0;	buf = (UINTN *)adjust_pointer(p);	while (*str && *str >= CHAR_NUM0 && *str <= CHAR_NUM9) str++;	if (*str) {		config_error(L"%s is expecting a numeric decimal value", p->name);		return -1;	}	tmp = Atoi(numstr);	if (p->check && p->check(&tmp) == -1) return -1;	/*	 * check for multiple definitions in the same context	 * XXX: zero must not be a valid number !	 */	if (*buf) {		config_error(L"option %s is already defined in this context", p->name);		return -1;	}	*buf = tmp;	return 0;}static INTNcheck_verbosity(VOID *data){	UINTN *val = (UINTN *)data;	if (*val > 5) {		config_error(L"Verbosity level must be in [0-5] and not %d", *val);		return -1;	}	return 0;}/* * here we simply check if chooser is compiled in. At this point, the chooser * initialization is not done, so we don't know if that chooser will even be * useable. */static INTNcheck_chooser(VOID *data){	CHAR16 *chooser = (CHAR16 *)data;	if (exist_chooser(chooser) == -1) {		config_error(L"chooser %s is unknown\n", chooser);		return -1;	}	return 0;}static INTNdo_string_core(config_option_t *p, CHAR16 *str, UINTN maxlen, CHAR16 *msg){	token_t tok;	CHAR16 *buf;	/*	 * match the '=' sign	 */	tok = get_token(str, maxlen);	if (tok != TOK_EQUAL) {		config_error(L"Option %s expects an equal signal + %s", p->name, msg);		return -1;	}	/*	 * now get the value	 */	tok = get_token(str, maxlen);	if (tok != TOK_STR) {		config_error(L"Option %s expects %s", p->name, msg);		return -1;	}	/*	 * if there is a customized way of doing the operation	 * do it and bypass generic	 */	if (p->action) return p->action(p, str);	/*	 * no field to update	 */	if (p->data == NULL) return 0;	buf = adjust_pointer(p);	if (*buf != CHAR_NULL) {		config_error(L"'%s' already defined", p->name);		return -1;	}	if (p->check && p->check(str) == -1) return -1;	/*	 * initialize field	 */	StrCpy(buf, str);	return 0;}	static INTNdo_string(config_option_t *p){	CHAR16 str[MAX_STRING];	return do_string_core(p, str, MAX_STRING, L"string");}	static INTNdo_file(config_option_t *p){	CHAR16 str[FILENAME_MAXLEN];	return do_string_core(p, str, FILENAME_MAXLEN, L"filename");}static INTNdo_cmd(config_option_t *p){	CHAR16 str[CMDLINE_MAXLEN];	return do_string_core(p, str, CMDLINE_MAXLEN, L"kernel options");}INTNconfig_parse(VOID){	CHAR16 str[MAX_STRING];	INTN ret = -1;	token_t tok;	config_option_t *p;	for (;;) {		tok = get_token(str, MAX_STRING);		if (tok == TOK_EOF) break;		if (tok == TOK_ERR) return -1;		if ( (p = find_option(current_options, str)) == NULL) {			config_error(L"Unkown option %s", str);			return -1;		}		/* make sure we trap in case of error */		ret = -1;		switch(p->type) {			case OPT_BOOL:				ret = do_boolean(p);				break;			case OPT_STR:				ret = do_string(p);				break;			case OPT_NUM:				ret = do_numeric(p);				break;			case OPT_FILE:				ret = do_file(p);				break;			case OPT_CMD:				ret = do_cmd(p);				break;			default:				config_error(L"Unkown option type %d", p->type);		}		if (ret == -1) goto error;	}	if (current_img) {		ret = image_check(current_img);		} else {		config_error(L"No image defined !");	}	if (ret == 0) ret = final_check();error:	return ret;}	static VOIDupdate_elilo_opt(VOID){	/*	 * update boolean options first	 * Rule: by default not set unless explcitely requested on command line	 * therefore we can just update from global_config is set there.	 */	if (global_config.alt_check) elilo_opt.alt_check = 1;	if (global_config.debug) elilo_opt.debug   = 1;	if (global_config.prompt) elilo_opt.prompt = 1;	/*	 * update only if not set on command line	 * XXX: rely on the existence of a non-valid value as a marker than	 * the option was not specified on the command line	 */	if (global_config.verbose && elilo_opt.verbose == 0) 		elilo_opt.verbose = global_config.verbose;	if (global_config.chooser[0] && elilo_opt.chooser[0] == 0)		StrCpy(elilo_opt.chooser, global_config.chooser);	/*	 * if edd30_no_force not set by command line option but via config	 * file, then propagate	 */	if (global_config.edd30_no_force && elilo_opt.edd30_no_force == 0)		elilo_opt.edd30_no_force = 1;	/*	 * Difficult case of numeric where 0 can be a valid value	 * XXX: find a better way of handling these options!	 */	if (global_config.delay && elilo_opt.delay_set == 0)		elilo_opt.delay = global_config.delay;	/* readjusted by caller if necessary. 0 not a valid value here */	elilo_opt.timeout = global_config.timeout;	/* initrd is updated later when we have an image match */}/* * When called after read_config(), this function returns the config file * used by the loader, or NULL if no file was found. */CHAR16 *get_config_file(VOID){	return global_config.config_file[0] ? global_config.config_file : NULL; }EFI_STATUSread_config(CHAR16 *filename){	EFI_STATUS status;	INTN ret;		if (filename == NULL) return EFI_INVALID_PARAMETER;	VERB_PRT(3, Print(L"trying config file %s\n", filename));	StrCpy(global_config.config_file, filename);	status = fops_open(filename, &config_fd);	if (EFI_ERROR(status)) {                VERB_PRT(3, Print(L"cannot open config file %s\n", filename));                return status;	}	/*	 * start numbering at line 1	 */	line_num = 1;	ret = config_parse();	fops_close(config_fd);	DBG_PRT((L"done parsing config file\n"));	if (ret != 0) return EFI_INVALID_PARAMETER;	update_elilo_opt();	return EFI_SUCCESS;}VOIDprint_label_list(VOID){	boot_image_t *img, *dfl = global_config.default_image;	if (dfl) Print(L"%s ", dfl->label);	for (img = image_list; img; img = img->next) {		if (img != dfl) Print(L"%s   ", img->label);	}}/* Make labels and corresponding descriptions available to choosers.  The * idea is that the caller passes NULL for 'prev'; the first time, and * passes the previously returned value on subsequent calls.  The caller * repeats until this fn returns NULL. */VOID *get_next_description(VOID *prev, CHAR16 **label, CHAR16 **description){	boot_image_t *img = (boot_image_t *)prev;	if (img == NULL)		img = image_list;	else		img = img->next;	if (img) {		*label = img->label;		*description = img->description;		return (void *)img;	}	else		return NULL;}/* * find a description using the label name * return NULL if label not found or no description defined */CHAR16 *find_description(CHAR16 *label){	boot_image_t *img;	/* Attempt to find the image name now */	for (img = image_list; img; img = img->next) {		if (StriCmp(img->label, label) == 0) {			return img->description;		}	}	return NULL;}INTNfind_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd){	boot_image_t *img;	if (label == NULL) {		if (global_config.default_image == NULL) return -1;		img = global_config.default_image;		goto found;	}	options[0] = 0;	/* Attempt to find the image name now */	for (img = image_list; img; img = img->next) {		if (StriCmp(img->label, label) == 0) {			goto found;		}	}	/*	 * when the label does not exist, we still propagate the global options	 */	if (global_config.root[0]) {		StrCpy(options, L" root=");		StrCat(options, global_config.root);	}	if (global_config.options[0]) {		StrCat(options, L" ");		StrCat(options, global_config.options);	}	if (global_config.readonly) StrCat(options, L" ro");	if (global_config.initrd[0]) StrCpy(initrd, global_config.initrd);	/* make sure we don't get garbage here */	elilo_opt.sys_img_opts = NULL;	return -1;found:	StrCpy(kname, img->kname);	/*	 * literal option overrides any other image-based or global option	 *	 * In any case, the image option has priority over the global option	 */	if (img->literal == 0) {		if (img->root[0] || global_config.root[0]) {			StrCat(options, L"root=");			StrCat(options, img->root[0] ? img->root : global_config.root);		}		/* XXX: check max length */		if (img->options[0] || global_config.options[0]) {			StrCat(options, L" ");			StrCat(options, img->options[0] ? img->options: global_config.options);		}		if (img->readonly || global_config.readonly) {			StrCat(options, L" ro");		}	} else {		/* literal options replace everything */		StrCpy(options, img->options);	}	/* per image initrd has precedence over global initrd */	if (img->initrd[0]) 		StrCpy(initrd, img->initrd);	else if (global_config.initrd[0])		StrCpy(initrd, global_config.initrd);	/*	 * point to architecture dependent options for this image	 */	elilo_opt.sys_img_opts = &img->sys_img_opts;	DBG_PRT((L"label %s: kname=%s options=%s initrd=%s", img->label, kname, options, initrd));	return 0;}static VOIDprint_options(config_option_group_t *grp, BOOLEAN first){	config_option_t *end, *p;	CHAR16 *str;	while (grp) {		p = grp->options;		end = grp->options+grp->nentries;		while (p != end) {			str = NULL;			switch(p->type) {				case OPT_BOOL:					str = L"%s";					break;				case OPT_STR :					str = L"%s=string";					break;				case OPT_FILE :					str = L"%s=filename";					break;				case OPT_CMD :					str = L"%s=kernel_options";					break;				case OPT_NUM :					str = L"%s=number";					break;				default: 					break;			}			if (str && first == FALSE) Print(L", ");			if (str) Print(str, p->name);			first = FALSE;			p++;		}		grp = grp->next;	}}VOIDprint_config_options(VOID){	Print(L"Global options supported:\n");	print_options(global_option_list, TRUE);	Print(L"\n\n");	Print(L"Image options supported:\n");	print_options(image_option_list, TRUE);	Print(L"\n");}/* * returns a pointer to filename used for message N (which). NULL if it does * not exist. */CHAR16 *get_message_filename(INTN which){	if (which < 0 || which >= MAX_MESSAGES) return NULL;	return global_config.message_file[which];}INTNregister_config_options(config_option_t *opt, UINTN n, config_option_group_scope_t group){	config_option_group_t *newgrp, **grp;	if (opt == NULL || n == 0 || (group != OPTIONS_GROUP_GLOBAL && group != OPTIONS_GROUP_IMAGE)) return -1;	VERB_PRT(3, Print(L"registering %d options for group %s\n", n, group == OPTIONS_GROUP_GLOBAL ? L"global" : L"image"));	newgrp = alloc(sizeof(config_option_group_t), EfiLoaderData);	if (newgrp == NULL) return -1;	grp = group == OPTIONS_GROUP_GLOBAL ? &global_option_list : &image_option_list;	if (*grp) while ((*grp)->next) grp = &(*grp)->next;	newgrp->options  = opt;	newgrp->next     = NULL;	newgrp->nentries = n;	if (*grp) { 		(*grp)->next = newgrp;	} else {		*grp = newgrp;		}	return 0;}/* * initialize config options: register global and per image options */INTNconfig_init(VOID){	INTN ret;	ret = register_config_options(global_common_options, 		  	              sizeof(global_common_options)/sizeof(config_option_t),				      OPTIONS_GROUP_GLOBAL);	if (ret == -1) return -1;	ret = register_config_options(image_common_options, 				      sizeof(image_common_options)/sizeof(config_option_t),				      OPTIONS_GROUP_IMAGE);	current_options = global_option_list;	return ret;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?