📄 first32.c
字号:
#include "stddef.h"#include "string.h"#include "linux-asm-io.h"#include "etherboot.h"#include "start32.h"#include "elf_boot.h"#ifndef FIRST32DOS#define FIRST32LINUX 1#endif#ifdef FIRST32LINUX#define SERIAL_CONSOLE 0/* * 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. *//*Memory layout assumed by mknbi and this program0x07C00-0x07FFF 0.5 kB floppy boot sector if loaded from floppy0x0F???-0x0FFFF ? kB large Etherboot data buffers (deprecated)0x10000-0x8FFFF 512.0 kB kernel (from tagged image)0x90000-0x901FF 0.5 kB Linux floppy boot sector (from Linux image)0x90200-0x921FF 8.0 kB kernel setup (from Linux image)0x92200-0x923FF 0.5 kB tagged image header ("directory")0x92400-0x927FF 1.0 kB kernel parameters (generated by mknbi)0x92800-0x93FFF 6.0 kB this program (generated by mknbi)0x94000-0x9FFFF 48.0 kB Etherboot (top few kB may be used by BIOS) Normally Etherboot starts at 0x940000x100000- kernel (if bzImage) (from tagged image)after bzImage kernel ramdisk (optional) (from tagged image) moved to below top of memory by this program but not higher than 896kB or what the limit in setup.S says*/#define PARAMSIZE 512extern void printf(const char *, ...);extern int sprintf(char *, const char *, ...);extern void xstart(unsigned long);extern void exit(int);#ifdef FIRST32ELFstatic Elf32_Phdr *seg[S_END] = { 0 };#elsestatic struct segment *seg[S_END] = { 0 };#endifstatic unsigned char *ip, *op;static short *vgamode;static struct bootp_t *bp;static unsigned char *vendortags;unsigned long top_of_initrd = 0;static enum { RD_TOP, RD_ASIS, RD_HEXADDR } rdmode = RD_TOP;static unsigned long rdaddr;#if SERIAL_CONSOLE/* Base Address */#define TTYS0 0x3f8/* Data */#define TTYS0_RBR (TTYS0+0x00)#define TTYS0_TBR (TTYS0+0x00)/* Control */#define TTYS0_IER (TTYS0+0x01)#define TTYS0_IIR (TTYS0+0x02)#define TTYS0_FCR (TTYS0+0x02)#define TTYS0_LCR (TTYS0+0x03)#define TTYS0_MCR (TTYS0+0x04)#define TTYS0_DLL (TTYS0+0x00)#define TTYS0_DLM (TTYS0+0x01)/* Status */#define TTYS0_LSR (TTYS0+0x05)#define TTYS0_MSR (TTYS0+0x06)#define TTYS0_SCR (TTYS0+0x07)static void ttys0_tx_byte(unsigned byte){ while((inb(TTYS0_LSR) & 0x20) == 0) ; outb(byte, TTYS0_TBR);}#endifvoid putchar(int c){ if (c == '\n') putchar('\r');#if SERIAL_CONSOLE ttys0_tx_byte(c);#endif console_putc(c);}static inline void quit(void){ printf("Bad argument\n"); exit(0);}static void nomem(void){ printf("Out of parameter space\n"); exit(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;}#ifdef FIRST32ELFstatic inline void locate_segs(union infoblock *header){ int i; Elf32_Phdr *s; s = (Elf32_Phdr *)((char *)header + header->ehdr.e_phoff); for (i = 0; i < S_END && i < header->ehdr.e_phnum; i++, s++) { seg[i] = s;#if DEBUG > 1 printf("%d %#X\n", i, s->p_paddr);#endif }}#elsestatic inline void locate_segs(union infoblock *header){ int i; struct segment *s; s = (struct segment *)((char *)header + sizeof(struct imgheader) + ((header->img.length & 0xF0) >> 2)); for (i = 0; i < S_END; i++, s++) { seg[i] = s;#if DEBUG > 1 printf("%d %#X\n", i, s->p_paddr);#endif if (s->flags & F_FINAL) break; s = (struct segment *)((char *)s + ((s->lengths & 0xF0) >> 2)); }}#endif /* !FIRST32ELF *//* * Find DHCP vendor tag, return pointer to tag length */static unsigned char *gettag(unsigned int tag){ unsigned char *p; unsigned char c; static unsigned char emptytag[] = { 0, 0 }; if (vendortags == 0) return (emptytag); for (p = vendortags; (c = *p) != RFC1533_END; ) { if (c == RFC1533_PAD) p++; else if (c == tag) return (p + 1); else p += p[1] + 2; } return (emptytag);}static void outtag(unsigned char *value){ int len; len = *value++; if (op + len > ip) nomem(); while (len-- > 0) *op++ = *value++;}/* Return 1 if s2 is a prefix of s1 */static int strprefix(const unsigned char *s1, const unsigned char *s2){ while (*s1 != '\0' && *s2 != '\0' && *s1++ == *s2++) ; /* Have we reached the end of s2? */ return (*s2 == '\0');}enum keyword { K_VGA, K_NFSROOT, K_IP, K_RDBASE, K_MEM };static inline int match_keyword(const unsigned char *start){ if (strprefix(start, "vga")) return (K_VGA); if (strprefix(start, "nfsroot")) return (K_NFSROOT); if (strprefix(start, "ip")) return (K_IP); if (strprefix(start, "rdbase")) return (K_RDBASE); if (strprefix(start, "mem")) return (K_MEM); return (-1);}#define isws(c) ((c) == ' ' || (c) == '\t')static inline int copy_and_match(void){ int c; unsigned char *start; start = ip; /* Stop copying at = if it exists */ while ((c = *ip) != '\0' && !isws(c) && c != '=') { *op++ = *ip++; } if (c == '=') { ip++; *op++ = '='; return (match_keyword(start)); } return (-1);}static unsigned long gethex(const unsigned char *p){ unsigned long value = 0; for (;;) { int c = *p++; if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'a' && c <= 'f') c -= 'a' - 10; else if (c >= 'A' && c <= 'F') c -= 'A' - 10; else break; value <<= 4; value |= c; } return (value);}static int getdec(const unsigned char *p){ int value = 0, sign = 0; if (*p == '-') { sign = 1; p++; } for (;;) { int c = *p++; if (c >= '0' && c <= '9') c -= '0'; else break; value *= 10; value += c; } return (sign ? -value : value);}static void copy_nonws(void){ int c; /* Copy up to next whitespace */ while ((c = *ip) != '\0' && !isws(c)) *op++ = *ip++;}static void discard_arg(void){ int c; /* Discard up to next whitespace */ while ((c = *ip) != '\0' && !isws(c)) ip++;}static int outip(const unsigned char *p){ long ip; if (*p == 0) return (0); memcpy(&ip, p + 1, sizeof(ip)); return sprintf(op, "%@", ip);}static inline void subst_value(int kwindex){ int c; unsigned char *p; if (kwindex == K_VGA) { /* backup over "vga=" */ op -= sizeof("vga=") - 1; if (strprefix(ip, "ask")) c = -3; else if (strprefix(ip, "extended")) c = -2; else if (strprefix(ip, "normal")) c = -1; else if (strprefix(ip, "0x")) c = gethex(ip+2); else /* assume decimal mode number */ c = getdec(ip); *vgamode = c; discard_arg(); } else if (kwindex == K_NFSROOT && strprefix(ip, "rom") && (ip[3] == '\0' || isws(ip[3]))) { outtag(gettag(RFC1533_ROOTPATH)); discard_arg(); } else if (kwindex == K_IP && strprefix(ip, "rom") && (ip[3] == '\0' || isws(ip[3]))) { long ip; op += sprintf(op, "%@:%@:", bp->bp_yiaddr, bp->bp_siaddr); p = gettag(RFC1533_GATEWAY); op += outip(p); *op++ = ':'; p = gettag(RFC1533_NETMASK); op += outip(p); *op++ = ':'; outtag(gettag(RFC1533_HOSTNAME)); p = gettag(RFC1533_VENDOR_ETHDEV); if (*p) *op++ = ':'; outtag(p); discard_arg(); } else if (kwindex == K_RDBASE) { if (strprefix(ip, "top")) rdmode = RD_TOP; else if (strprefix(ip, "asis")) rdmode = RD_ASIS; else if (strprefix(ip, "0x")) { rdmode = RD_HEXADDR; rdaddr = gethex(ip+2); } discard_arg(); } else if (kwindex == K_MEM) { unsigned char *p; unsigned long memsize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -