_A COFF FILE LOADER FOR THE 34010_ by Don Morgan [LISTING ONE] #include #include #include #include #include #include #include #include #include #include "coff.h" struct main_header *m_hdr; struct opt_header *opt; struct sect_header section; void main(int argc, char **argv) { /**************** PART A *****************/ int module, size, header, sect, j; unsigned long result; int bss_done = FALSE; unsigned char *receive_buffer; char tmp_buf[100]; int data, i; if(argc != 2) { printf("\nno file given!"); exit(-1); } module = open(argv[1], O_BINARY|O_RDONLY); if(module == -1){ perror("\nopen failed!"); exit(-1); } /**************************/ /*read coff file into buffer*/ size = filelength(module); file_buffer = (char *)malloc(size); if(file_buffer == NULL) { perror("\nnot enough memory!"); exit (-1); } if((result = (long)read(module, file_buffer, size)) <= 0) { perror("\ncan't find file!\n"); exit(-1); } close(module); /************ PART B *************/ /*set up 34010 for loading*/ /**************************/ /*it is the users responsibility to set up the cntrl register*/ /*please note that some of the register settings, such as the following*/ /*are application dependent, this code is included only to show an*/ /*example of low level setup for the 34010*/ gsp_poke(cntrl, 0x4); /*sets cas before ras refresh*/ /**************************/ /*set up 34010 to restart correctly after loading program*/ put_hstctl(hlt | cf | incr | incw | nmim | nmi_flg); data = get_hstctl(); if(data != (hlt | cf | incr | incw | nmim | nmi_flg)) { printf("\nerror writing to hstctl!"); exit(-1); } /************ PART C *************/ /**************************/ /*get contents of main header*/ m_hdr = (struct main_header *) file_buffer; /*see if the file has a magic number*/ if(m_hdr->magic_num !=FILE_MAGIC) { printf("\nnot a standard coff .out file!"); exit(-1); } /*check to see whether there is an optional header*/ if((m_hdr->opt_head != OPT_XST)){ printf("file is not fully linked!"); exit(-1); } /*get contents of optional header*/ opt = (struct opt_header *) &file_buffer[OPT_OFST]; /*see if the optional header has a magic number*/ if(opt->magic_num !=OPT_MAGIC) { printf("\nnon standard file!"); exit(-1); } /*************************************************/ /*begin searching for and loading section headers find bss section first! */ i = FIRST_HDR; for (j=0;((jnum_sects) && !bss_done) ;j++){ strcpy(tmp_buf,&file_buffer[i]); if(!bss_done) { if(!(strcmp(tmp_buf, ".bss"))) { strcpy(section.name, tmp_buf); header = i; get_sect(header); bss_done = TRUE; } } i += SEC_OFST; } /*now load the other sections*/ i = FIRST_HDR; for (j=0; jnum_sects;j++){ strcpy(tmp_buf,&file_buffer[i]); if(strcmp(tmp_buf, ".bss")) { strcpy(section.name, tmp_buf); header = i; get_sect(header); } i += SEC_OFST; } /*release memory for file buffer*/ free(file_buffer); /************ PART D *************/ /*set up reset and interrupt vectors for the 34010 */ /*usually, both the nmi and halt bits are set and then released */ /*this code may differ depending upon the desires of the programmer */ gsp_poke(intenb,0x0); /*no interrupts*/ gsp_poke(nmi_vect, opt->entry_point); gsp_poke(nmi_vect+0x10, opt->entry_point >> 0x10); gsp_poke(reset,opt->entry_point); gsp_poke(reset+0x10,opt->entry_point >> 0x10); put_hstctl(hlt | incr | nmi_flg | incw | nmim); /*toggle the halt bit and go*/ data = get_hstctl(); data &= ~hlt; put_hstctl( data ); } /*********** PART E *************/ void get_sect(header) int header; { struct sect_header * ptr = (struct sect_header *)&file_buffer[header]; load(ptr); } void load(ptr) struct sect_header *ptr; { /*here the flags are checked to determine whether the section is to be loaded or copied or ignored*/ if((ptr->sect_size) && !(ptr->flags & STYP_DSECT) && !(ptr->flags & STYP_NOLOAD)) { if(!(strcmp(ptr->name,".cinit")) && (ptr->flags & STYP_COPY)) put_data(ptr); else if(((ptr->flags & STYP_TEXT) || (ptr->flags & STYP_DATA) || (!(strcmp(ptr->name,".cinit") && !(ptr->flags & STYP_COPY))))) load_block(ptr); } } void load_block(ptr) struct sect_header *ptr; { int data, temporary, hldr, limit; long i, j, file_pointer; file_pointer = ptr->raw_data; /*set the host interface up to point at the correct address*/ #if MM *(gsp:>hstadrl) = ptr->virt_addr; *(gsp:>hstadrh) = ptr->virt_addr >> 0x10; #else outpw(io_hstadrl, (unsigned int)ptr->virt_addr); outpw(io_hstadrh, (unsigned int)ptr->virt_addr >> 0x10); #endif limit = (ptr->sect_size/0x10)-1; j=0; /*write each word to host interface*/ for(i=0; i<=limit; i++){ /*get the data from the file buffer and get it in the correct order before writing to the host interface*/ data = (file_buffer[file_pointer+j++]&0xff); data += ((file_buffer[file_pointer+j++]&0xff)*0x100); #if MM *(gsp:>hstdata) = data; #else outpw(io_hstdata,data); #endif } /*compare data*/ /*point at the correct address*/ #if MM *(gsp:>hstadrl) = ptr->virt_addr; *(gsp:>hstadrh) = ptr->virt_addr >> 0x10; #else outpw(io_hstadrl, (unsigned int)ptr->virt_addr); outpw(io_hstadrh, (unsigned int)ptr->virt_addr>> 0x10); #endif limit = (ptr->sect_size/0x10)-1; j=0; for(i=0; i<=limit; i++){ /*get the data*/ data = (file_buffer[file_pointer+j++]&0xff); data += ((file_buffer[file_pointer+j++]&0xff)*0x100); #if MM hldr = *(gsp:>hstdata); #else hldr = inpw(io_hstdata); #endif if(hldr != data) printf("\ncompare error!"); } } void put_data(ptr) struct sect_header *ptr; { int data, temporary, hldr, limit, num_words, num; long i, j, reloc_address, file_pointer; struct init_table * init; file_pointer = ptr->raw_data; do{ init = (struct init_table *)&file_buffer[file_pointer]; reloc_address = init->ptr_to_var; file_pointer += 6; /*point at relocation address*/ #if MM *(gsp:>hstadrl) = reloc_address; *(gsp:>hstadrh) = reloc_address >> 0x10; #else outpw(io_hstadrl, (unsigned int)reloc_address); outpw(io_hstadrh, (unsigned int)reloc_address >> 0x10); #endif /*determine the amount of data to transfer and do it*/ num_words = init->num_words; limit = --num_words; j=0; for(i=0; i<=limit; i++){ data = (file_buffer[file_pointer+j++]&0xff); data += ((file_buffer[file_pointer+j++]&0xff)*0x100); #if MM *(gsp:>hstdata) = data; #else outpw(io_hstdata,data); #endif } /*now, do a data compare*/ #if MM *(gsp:>hstadrl) = reloc_address; *(gsp:>hstadrh) = reloc_address >> 0x10; #else outpw(io_hstadrl, (unsigned int)reloc_address); outpw(io_hstadrh, (unsigned int)reloc_address >> 0x10); #endif num_words = init->num_words; limit = --num_words; j=0; for(i=0; i<=limit; i++){ data = (file_buffer[file_pointer+j++]&0xff); data += ((file_buffer[file_pointer+j++]&0xff)*0x100); #if MM hldr = *(gsp:>hstdata); #else hldr = inpw(io_hstdata); #endif if(hldr != data) printf("\ndata compare error!"); } file_pointer += j; }while(((int)file_buffer[file_pointer]) != 0x0); } /*set up the hstctl*/ void put_hstctl(unsigned int value) { #if MM *(gsp:>hstctl) = value; #else outpw(io_hstctl,value); #endif } /*get current Hstclt setting*/ unsigned int get_hstctl() { int value; #if MM value = *(gsp:>hstctl); #else value = inpw(io_hstctl); #endif return value; } /*set host interface to point at correct address*/ void set_addr(unsigned long address) { #if MM *(gsp:>hstadrl) = address; *(gsp:>hstadrh) = address >> 0x10; #else outpw(io_hstadrl,(unsigned int)address); outpw(io_hstadrh,(unsigned int)address >> 0x10); #endif } void gsp_poke(unsigned long address, unsigned long value) { set_addr(address); #if MM *(gsp:>hstdata) = value; #else outpw(io_hstdata,(unsigned int)value); #endif } unsigned int gsp_peek(unsigned long address) { int value; set_addr(address); #if MM value = *(gsp:>hstdata); #else value = inpw(io_hstdata); #endif return value; } [LISTING TWO] #define FALSE 0 #define TRUE 0x1 #define MM TRUE /*physical addresses of memory mapped host interface*/ #if MM _segment gsp = 0xc700; int _based(void) *hstctl = (int _based(void)*)0xe00; int _based(void) *hstdata = (int _based(void)*)0xf00; int _based(void) *hstadrh = (int _based(void)*)0xc00; int _based(void) *hstadrl = (int _based(void)*)0xd00; #else /*io mapped addresses of host interface*/ io_hstctl = 0; io_hstdata = 0; io_hstadrh = 0; io_hstadrl = 0; #endif #define FILE_MAGIC 0x90 #define OPT_MAGIC 0x108 #define OPT_XST 0x1c #define OPT_OFST 0x14 #define SEC_OFST 0x28 #define FIRST_HDR 0x30 #define cf 0x4000 #define hlt 0x8000 #define nmi_flg 0x100 #define nmim 0x200 #define incw 0x800 #define incr 0x1000 /*definitions*/ /*file header flags*/ #define F_RELFLG 0x1 /*relocation information stripped*/ #define F_EXEC 0x2 /*file is relocateable*/ #define F_LNNO 0x4 /*line numbers stripped*/ #define F_LSYMS 0x10 /*local symbos stripped*/ #define F_QR32WR 0x40 /*34010 byte ordering*/ /*section header flags*/ #define STYP_REG 0x0 /*regular section*/ #define STYP_DSECT 0x1 /*dummy section*/ #define STYP_NOLOAD 0x2 /*noload section*/ #define STYP_GROUP 0x4 /*grouped section*/ #define STYP_PAD 0x8 /*padding section*/ #define STYP_COPY 0x10 /*copy section, important for .cinit*/ #define STYP_TEXT 0x20 /*executable code*/ #define STYP_DATA 0x40 /*initialized data*/ #define STYP_BSS 0x80 /*uninitialized data*/ #define STYP_ALIGN 0x100 /*aligned on cache boundary*/ /*******************************************************/ /*interrupt vector:*/ #define reset 0xffffffe0 #define nmi_vect 0xfffffee0 /*******************************************************/ /*i/o registers:*/ #define refcnt 0xc00001f0 #define dpyadr 0xc00001e0 #define vcount 0xc00001d0 #define hcount 0xc00001c0 #define dpytap 0xc00001b0 #define pmask 0xc0000160 #define psize 0xc0000150 #define convdp 0xc0000140 #define convsp 0xc0000130 #define intpend 0xc0000120 #define intenb 0xc0000110 #define hstctlh 0xc0000100 #define hstctll 0xc00000f0 #define hst_adrh 0xc00000d0 #define hst_adrl 0xc00000e0 #define hst_data 0xc00000c0 #define cntrl 0xc00000b0 #define dpyint 0xc00000a0 #define dpystrt 0xc0000090 #define dpyctl 0xc0000080 #define vtotal 0xc0000070 #define vsblnk 0xc0000060 #define veblnk 0xc0000050 #define vesync 0xc0000040 #define htotal 0xc0000030 #define hsblnk 0xc0000020 #define heblnk 0xc0000010 #define hesync 0xc0000000 #define dac_wr 0xc7800 #define ppl_rd 0xc7000 /*header structures*/ struct main_header { unsigned short int magic_num; unsigned short int num_sects; long int date_stamp; long int sym_table; long int entries; unsigned short int opt_head; unsigned short int flags; }; struct opt_header { short int magic_num; short int version; unsigned long code_size; unsigned long init_size; unsigned long uninit_size; unsigned long entry_point; unsigned long start_text; unsigned long start_data; }; struct sect_header { unsigned char name[8]; unsigned long phys_addr; unsigned long virt_addr; unsigned long sect_size; unsigned long raw_data; unsigned long reloc; unsigned long num_entries; unsigned short int reloc_entries; unsigned short int line_entries; unsigned short int flags; unsigned char ch1; unsigned char page; }; struct init_table { int num_words; long ptr_to_var; }; /*video pointer*/ char far *vid_mem; /*variable declarations*/ int len, text_ptr, debug, coff_debug, fake; unsigned char *file_buffer; /*function prototypes*/ long getint(int, int); void load(struct sect_header *); void load_block(struct sect_header *); void put_data(struct sect_header *); void put_hstctl(unsigned int); unsigned int get_hstctl(void); void set_addr(unsigned long int); void gsp_poke(unsigned long int, unsigned long int); unsigned int gsp_peek(unsigned long int); void get_sect(int);