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 + -
显示快捷键?