/* l.out.c -- routines for manipulating l.out executable files. */ #include <l.out.h> #include <canon.h> #include <sys/types.h> #include "tboot.h" /* Convert l.out to load table. * Used to generate loading instructions for use by tboot main(). * Returns true on successful translation. */ int lout2load(ip, table, data_seg) struct inode *ip; /* input: File to read. */ struct load_segment table[]; /* output: How to read it. */ uint16 *data_seg; /* output: Where to point es. */ { int i; /* Loop counter. */ struct ldheader imageheader; /* l.out header for boot image. */ VERBOSE( puts("Reading the l.out header.\r\n"); ); /* Read the header. */ iread(ip, &imageheader, (fsize_t) 0, (uint16) sizeof(struct ldheader)); /* Canonicalize the header. */ canint(imageheader.l_magic); canint(imageheader.l_flag); canint(imageheader.l_machine); canvaddr(imageheader.l_entry); for(i = 0; i < NLSEG; ++i) { cansize(imageheader.l_ssize[i]); } /* Copy the l.out header info into table. */ #define L_TEXT table[0] #define L_DATA table[1] /* Calculate remaining entries. */ if (imageheader.l_flag & LF_SEP) { /* if sep i/d executable */ VERBOSE( puts("Generating table for sep i/d l.out.\r\n"); ); L_TEXT.valid = (1==1); L_TEXT.message = "\r\nLoading 286 COHERENT...\r\n"; /* Load the shared and private code segments as one. */ L_TEXT.load_toseg = sys_base; /* This is where we want the OS. */ L_TEXT.load_tooffset = 0; L_TEXT.load_offset = sizeof(struct ldheader); /* Skip the header. */ L_TEXT.load_length = imageheader.l_ssize[L_SHRI] + /* Both segments as one. */ imageheader.l_ssize[L_PRVI]; L_DATA.valid = (1==1); L_DATA.message = "\r\nLoading 286 COHERENT data...\r\n"; /* Load both data segments. */ /* Round up to next 16 byte paragraph. */ L_DATA.load_toseg = (sys_base + (imageheader.l_ssize[L_SHRI] + /* Shared code */ imageheader.l_ssize[L_PRVI] + /* Private code */ 15) / 16); L_DATA.load_tooffset = 0; L_DATA.load_offset = (fsize_t) sizeof(struct ldheader) + /* l.out header */ imageheader.l_ssize[L_SHRI] + /* Shared code */ imageheader.l_ssize[L_PRVI]; /* Private code */ L_DATA.load_length = imageheader.l_ssize[L_SHRD] + /* Both segments as one. */ imageheader.l_ssize[L_PRVD]; table[2].valid = (1==2); /* Terminate the list. */ *data_seg = (uint16) (sys_base + (imageheader.l_ssize[L_SHRI] + /* Shared code */ imageheader.l_ssize[L_PRVI] + /* Private code */ 15) / 16); /* Rounded up a paragraph. */ } else { /* if not sep i/d executable */ #define SEGMENT table[0] VERBOSE( puts("Generating table for non-sep i/d l.out.\r\n"); ); SEGMENT.valid = (1==1); SEGMENT.message = "\r\nLoading ancient COHERENT...\r\n"; /* Load the shared and private code segments as one. */ SEGMENT.load_toseg = sys_base; /* This is where we */ SEGMENT.load_tooffset = 0; /* want the OS. */ /* Skip the header. */ SEGMENT.load_offset = (fsize_t) sizeof(struct ldheader); /* Load all segments as one. */ SEGMENT.load_length = imageheader.l_ssize[L_SHRI] + imageheader.l_ssize[L_PRVI] + imageheader.l_ssize[L_SHRD] + imageheader.l_ssize[L_PRVD]; table[1].valid = (1==2); /* Terminate the list. */ /* Tiny model: ds = cs */ *data_seg = sys_base; } /* if not sep i/d executable */ return (1==1); } /* * Wrapper for l_out_nlist() to make it look palitable. */ unsigned int wrap_l_out_nlist(filename, symbol) char *filename; char *symbol; { struct nlist nlp[2]; /* For talking with l_out_nlist(). */ strcpy(nlp[0].n_name, symbol); strcat(nlp[0].n_name, "_"); nlp[1].n_name[0] = '\0'; l_out_nlist(filename, nlp); return( nlp[0].n_value ); } /* * Get entries from l.out name list. */ void l_out_nlist(fn, nlp) char *fn; struct nlist *nlp; { register struct nlist *np; register int ntodo = 0; int lfp; struct ldheader lh; struct ldsym ste; fsize_t symsize; register int n; for (np = nlp; np->n_name[0] != '\0'; np++) { np->n_type = np->n_value = 0; ntodo++; } if ((lfp = open(fn, 0)) == -1) return; n = read(lfp, &lh, sizeof lh); canint(lh.l_magic); if (n!=sizeof(lh) || lh.l_magic!=L_MAGIC) { puts("L.out bad MAGIC.\r\n"); close(lfp); return; } for (n=0; n<=L_SYM; n++) cansize(lh.l_ssize[n]); symsize = sizeof lh + lh.l_ssize[L_SHRI] + lh.l_ssize[L_SHRD] + lh.l_ssize[L_PRVI] + lh.l_ssize[L_PRVD] + lh.l_ssize[L_DEBUG]; lseek(lfp, symsize, 0); symsize = lh.l_ssize[L_SYM]; for ( ; symsize>0 && ntodo; symsize -= sizeof ste) { if (read(lfp, &ste, sizeof ste) != sizeof(ste)) break; for (np = nlp; np->n_name[0] != '\0'; np++) if (strncmp(np->n_name, ste.ls_id, NCPLN) == 0) { canint(ste.ls_type); canvaddr(ste.ls_addr); np->n_type = ste.ls_type; np->n_value = ste.ls_addr; if (--ntodo == 0) break; } } close(lfp); }