📄 menu.c
字号:
#include "stddef.h"#include "string.h"#include "printf.h"#include "ansiesc.h"#include "misc.h"#include "linux-asm-io.h"#include "etherboot.h"#include "startmenu.h"#include "elf_boot.h"#include "bootmenu.h"/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. *//*This is an example program which shows how the extension routinefeature in Etherboot 5.0 works.This program is linked to run at 0x60000, and expects to find configdata if any at 0x70000. This means the code can be up to 64kB long.When the program starts it receives 3 parameters from Etherboot:Pointer to ebinfo structurePointer to image header structure (either a tagged or ELF image header)Pointer to bootp/DHCP reply obtained by Etherboot from bootpd or DHCPDEtherboot expects this program to return an int. The values have thesemeanings:<0 Do not use0 Same as 1, for implementation reasons1 Redo tftp with possibly modified bootp record2 Redo bootp and tftp255 Exit EtherbootObserve that this program causes Etherboot to load a different programnext by modifying the contents of the filename field in the bootp recordand then returning 1. It can also send parameters to the next program bymodifying tag 129 in the bootp record.*//*Memory layout assumed by mknbi and this program0x60000-0x6FFFF 64 kB Menu program0x70000-0x7FFFF 64 kB Menu data (initial)*/static unsigned char *vendortags;static unsigned char *end_of_rfc1533;#ifdef IMAGE_FREEBSD /* yes this is a pain FreeBSD uses this for swap, however, there are cases when you don't want swap and then you want this set to get the extra features so lets just set if dealing with FreeBSD. I haven't run into any troubles with this but I have without it */static int vendorext_is_valid = 1;#elsestatic int vendorext_is_valid = 0;#endifstatic unsigned char *motd[RFC1533_VENDOR_NUMOFMOTD] = { 0 };static unsigned char *imagelist[RFC1533_VENDOR_NUMOFIMG] = { 0 };static inline void checkvendor(void){ union { unsigned long l; unsigned char c[4]; } u; memcpy(u.c, vendortags, sizeof(u)); if (u.l == RFC_1048 || u.l == VEND_CMU || u.l == VEND_STAN) vendortags += 4; else vendortags = 0;}static void parsebootp(){ unsigned char *p; unsigned int c; static unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* 銭th */ memset(motd, 0, sizeof(motd)); memset(imagelist, 0, sizeof(imagelist)); if (vendortags == 0) return; for (p = vendortags; (c = *p) != RFC1533_END; ) { if (c == RFC1533_PAD) { p++; continue; }#if DEBUG > 1 printf("Tag %d\n", c);#endif switch (c) { case RFC1533_VENDOR_MAGIC: if (TAG_LEN(p) >= 6 && !memcmp(p+2, vendorext_magic, 4) && p[6] == RFC1533_VENDOR_MAJOR) vendorext_is_valid = 1; break; case RFC1533_VENDOR_MENUOPTS: parse_menuopts(p+2, TAG_LEN(p)); break; default: if (c >= RFC1533_VENDOR_MOTD && c < RFC1533_VENDOR_MOTD + RFC1533_VENDOR_NUMOFMOTD) motd[c-RFC1533_VENDOR_MOTD] = p; else if (c >= RFC1533_VENDOR_IMG && c < RFC1533_VENDOR_IMG + RFC1533_VENDOR_NUMOFIMG) imagelist[c-RFC1533_VENDOR_IMG] = p; break; } p += p[1] + 2; } end_of_rfc1533 = p;}static void parse_elf_boot_notes( void *notes, union infoblock **rheader, struct bootpd_t **rbootp){ unsigned char *note, *end; Elf_Bhdr *bhdr; Elf_Nhdr *hdr; bhdr = notes; if (bhdr->b_signature != ELF_BHDR_MAGIC) { return; } note = ((char *)bhdr) + sizeof(*bhdr); end = ((char *)bhdr) + bhdr->b_size; while (note < end) { unsigned char *n_name, *n_desc, *next; hdr = (Elf_Nhdr *)note; n_name = note + sizeof(*hdr); n_desc = n_name + ((hdr->n_namesz + 3) & ~3); next = n_desc + ((hdr->n_descsz + 3) & ~3); if (next > end) break;#if 0 printf("n_type: %x n_name(%d): n_desc(%d): \n", hdr->n_type, hdr->n_namesz, hdr->n_descsz);#endif if ((hdr->n_namesz == 10) && (memcmp(n_name, "Etherboot", 10) == 0)) { switch(hdr->n_type) { case EB_BOOTP_DATA: *rbootp = *((void **)n_desc); break; case EB_HEADER: *rheader = *((void **)n_desc); break; default: break; } } note = next; }}int menu(struct ebinfo *eb, union infoblock *header, struct bootpd_t *bootp){ int i; extern int serial_init(void); extern void serial_fini(void);#ifdef DEBUG printf(MKNBI_VERSION "\n");#endif parse_elf_boot_notes(eb, &header, &bootp); /* Sanity check */ if (header->img.magic != ELF_MAGIC && header->img.magic != TAG_MAGIC) { printf("Bad argument passed from Etherboot\n"); return (255); } vendortags = (unsigned char *)bootp->bootp_reply.bp_vend; checkvendor(); parsebootp(); if (!vendorext_is_valid) { printf("No menu vendor tags found, returning to Etherboot\n"); sleep(10); return(2); }#ifdef CONSOLE_SERIAL serial_init();#endif#ifdef ANSIESC ansi_reset();#endif show_motd(motd); i = selectImage(bootp, imagelist, end_of_rfc1533); if (i == 2) { printf("No selection, returning to Etherboot\n"); sleep(10); }#ifdef CONSOLE_SERIAL serial_fini();#endif return (i);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -