📄 pnp.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)pnp.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1988-1990 by Sun Microsystems, Inc. */#include <sys/param.h>#include <sys/dir.h>#include <sys/user.h>#include <sys/uio.h>#include <sys/socket.h>#include <sys/kernel.h>#include <sys/ioctl.h>#include <sys/reboot.h>#include <sys/bootconf.h>#include <net/if.h>#include <net/if_arp.h>#include <netinet/in.h>#include <rpc/rpc.h>#include <rpc/pmap_rmt.h>#include <rpc/pmap_prot.h>#include <rpcsvc/pnprpc.h>#include <stand/saio.h>#ifndef sun3x#include <mon/cpu.addrs.h>#endif sun3x#include <mon/sunromvec.h>#include <mon/idprom.h>#ifdef sun386i#include <i386/380.h>#endif sun386i#include "boot/systm.h"#include "boot/if_ether.h"#ifdef DUMP_DEBUGstatic int dump_debug = 20;#endif /* DUMP_DEBUG */#undef ustruct user u;#ifdef DRARP_REQUESTextern int use_drarp;#endif#ifdef RPCDEBUGextern int rpcdebug;#endif /* Default "printf" is gated according to NVRAM verbosity control. * Bypass by using bpprintf ... here we REALLY want to see the * status, it's meaningful to very naive users. */#ifdef sun386i#define printf bpprintf#endif sun386i#define if_broadaddr if_addrlist->ifa_broadaddr/* * PNP Boot program ... downloaded when the network has granted * an IP address to this system, and it issues TFTP boot requests, * but no hostname is stored for this IP address. * * This follows the "plug'n'play" protocol to get configured on * the network or to generate reasonable diagnostics. * * Note ... bastardized from boot.c, there's a lot in this * boot program that can be deleted. All it really needs is to * issue RPCs! */struct bootparam *boot_bp;extern int memory_avail;extern struct ifnet *if_ifwithaf();#undef u;extern struct user u;extern struct in_addr my_in_addr;extern int ethernet_started; /* Checkpoints for progress meter. Defined according to * performance near FCS. */#define CHKPT_START 0#define CHKPT_VERIFY 5#define CHKPT_ACQUIRE 10#define CHKPT_SETUP 20#define CHKPT_POLL 30#define CHKPT_POLL_INCR 10#define CHKPT_BACKWARDS 75#define CHKPT_PNPDONE 100#define CHKPT_MAX 100#ifdef sun386static int chkpt_now = 0;#define PMeter(x) PROGRESS(chkpt_now = (x))#else#define PMeter(x)#endif sun386/* * Verbose mode -- * Not (yet) implemented. */extern int verbosemode;static char *msgs [] = { /* 000 series: fatal errors */#define MSG_NONPNPNET msgs[0] "This network does not support Automatic System Installation.",#define MSG_NOmesg msgs[1] "",#define MSG_NOSOFTWARE msgs[2] "No software for this architecture installed.",#define MSG_NOSPACE msgs[3] "Not enough disk space to support a diskless client.",#define MSG_NOCLIENTS msgs[4] "Unwilling to accept more clients.", /* 100 series: diagnostics, the user must take some action */#define MSG_SEEADMIN msgs[5] "See your Network Administrator to resolve this problem.",#define MSG_PROTOERR msgs[6] "A nonfatal protocol error ocurred. Installation may not work.", /* 200 series: diagnostics, information only */#define MSG_ACQUIRETIMEOUT msgs[7] "No server responded, restarting Automatic System Installation",#define MSG_POLLTIMEOUT msgs[8] "The server installing this system may have crashed, restarting.",#define MSG_RETRY msgs[9] "Retrying automatic system installation.",#define MSG_POLLERR msgs[10] "An error ocurred during the POLL sequence.",#define MSG_BUSYRETRY msgs[11] "The server is busy, retrying.",#define MSG_SETUPFAIL msgs[12] "The SETUP request failed, retrying.",#define MSG_WAIT msgs[13] "Your Network Administrator must configure this system.",#define MSG_WHOAREYOU msgs[14] "The server seems to have rebooted.",#define MSG_SETUPERR msgs[15] "Error in setup sequence.",};extern enum clnt_stat clntkudp_callit_addr ();static voidtwiddler (eh){ static char dialbuf [] = "|/-\\"; /* 4 chars */ static int i; if (!eh) { putchar (dialbuf [i++]); putchar ('\b'); i = i % 4; } else { putchar (' '); putchar ('\b'); i = 0; }}/* * pmapper remote-call-service interface. * This routine is used to call the pmapper remote call service * which will look up a service program in the port maps, and then * remotely call that routine with the given parameters. This allows * programs to do a lookup and call in one step. */static enum clnt_statpmap_rmtcall (call_addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, resp_addr) struct sockaddr_in *call_addr; u_long prog, vers, proc; xdrproc_t xdrargs, xdrres; caddr_t argsp, resp; struct timeval tout; struct sockaddr_in *resp_addr;{ register CLIENT *client; struct rmtcallargs a; struct rmtcallres r; enum clnt_stat stat; u_long port; call_addr->sin_port = htons(PMAPPORT); client = clntkudp_create(call_addr, PMAPPROG, PMAPVERS, 10, u.u_cred); if (client != (CLIENT *)NULL) { a.prog = prog; a.vers = vers; a.proc = proc; a.args_ptr = argsp; a.xdr_args = xdrargs; r.port_ptr = &port; r.results_ptr = resp; r.xdr_results = xdrres; /* XXX this call doesn't produce any sort of ongoing * activity indicator at all. UNFRIENDLY !! */ stat = clntkudp_callit_addr(client, PMAPPROC_CALLIT, xdr_rmtcall_args, (caddr_t)&a, xdr_rmtcallres, (caddr_t)&r, tout, resp_addr); resp_addr->sin_port = htons(port); CLNT_DESTROY(client); } else { printf("PNPBoot: remote call failed - port mapper failure?\n"); } return (stat);}static voidxsleep (nsec) register nsec;{ while (nsec-- > 0) { twiddler (0); DELAY (1000000); } twiddler (1);}static intinit_inet (ifpp) register struct ifnet **ifpp;{ register struct in_addr *ip1; /* ensure the net's started up and the tables are * initialized. */ if (!ethernet_started) { ethersetup (); domaininit (); ip_init (); ethernet_started++; } *ifpp = if_ifwithaf (AF_INET); if (!*ifpp) { printf ("?? No INET interface ??\n"); return -1; } if (!address_known (*ifpp)) revarp_myaddr (*ifpp); /* this is to ensure the interface has a valid IP * broadcast address. */ ip1 = &(((struct sockaddr_in *)&((*ifpp)->if_broadaddr))->sin_addr); ip1->s_net = my_in_addr.s_net; ip1->s_host = my_in_addr.s_host; ip1->s_lh = my_in_addr.s_lh; ip1->s_impno = 0; return 0;} /* This code will never get loaded except during a PNP sequence * on a pnp network ... but servers go away sometimes. Make * certain there's one to talk to. * TIME: 30 seconds max. */static intis_pnp_net (ifp) register struct ifnet *ifp;{ register int i; struct sockaddr_in pnpaddr; register enum clnt_stat stat; struct timeval tv; PMeter (CHKPT_VERIFY); tv.tv_sec = 15; tv.tv_usec = 0; for (i = 0; i < 2; i++) { twiddler (1); stat = pmap_rmtcall (&(ifp->if_broadaddr), (u_long)PNPD_PROG, (u_long)PNPD_VERS, NULLPROC, xdr_void, (char *) 0, xdr_void, (char *) 0, tv, &pnpaddr); if (!stat) { twiddler (1); return 1; } else twiddler (0); } return 0;} /* the only time this will succeed is if someone's changed the * network configuration, and this system is already known but * at a different location. * * This only supports automated installation just now, NOT * reconfiguration. */static pnp_errcodepnp_whoami (ifp) struct ifnet *ifp;{ PMeter (CHKPT_START); /* XXX IMPLEMENT * This requires a broadcast RPC mechanism. Pending * that, a complete restart of the boot sequence works, * though it's slower. */ xsleep (15); return pnp_success;}static voidlchex (where, val) char *where; u_char val;{ int i; static char x [17] = "0123456789abcdef"; i = (val >> 4) & 0x0f; where [0] = x [i]; i = val & 0x0f; where [1] = x [i];} /* assumes only one bootable INET interface, and it's * Ethernet/IEEE 802 48 bit. */static pnp_acquire_arg *get_acquire_arg (ifp) struct ifnet *ifp;{ static pnp_acquire_arg pa; static int didit = 0; static char hostid [9]; struct idprom id;#ifdef OPENPROMS register struct memlist *pmem;#endif if (!didit) { pa.linkaddr.hw = ethernet; myetheraddr (pa.linkaddr.hw_addr_u.enetaddr); pa.inetaddr = ntohl (my_in_addr.s_addr); /* pa.inetaddr = ntohl (ifp->if_addr.s_addr); */ /* architecture codes are 5 chars or less; they are * not always the same as the architecture. Cases * in mind: 68030 kernel won't run on a 68020, but * is the same from user mode; 'sun386' is too many * characters. (TFTP boot filenames must be 14 chars * or less, hence the 5 char limit.) */#if sun2 pa.arch = "sun2";#endif sun2#if sun3 pa.arch = "sun3";#endif sun3#if sun3x pa.arch = "sun3x";#endif sun3x#if sun4 pa.arch = "sun4";#endif sun4#if sun4c pa.arch = "sun4c";#endif sun4c#if sun386 pa.arch = "s386";#endif sun386 pa.how = b_diskless;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -