/* * download.c -- object file down load routine * * Copyright (C) 1997 by Sony Computer Entertainment * All rights Reserved */ /* #define DEBUGFIFO */ #include #include #include #include #include #include #include #include #include #include #include "cmdport.h" #include "fifoport.h" #include "download.h" #include "keyin.h" #include "display.h" #include "misc.h" #include "asm.h" #include "filehdr.h" #include "aouthdr.h" #include "scnhdr.h" #include "dosint.h" #include "rs.h" extern int prompt_catch_flag; extern FILE *logfp; /*------- data buffer --------*/ char databuf[DATABUFSIZE]; /*------- PSX EXE file format --------*/ struct EXEC { unsigned long pc0; unsigned long gp0; unsigned long t_addr; unsigned long t_size; unsigned long d_addr; unsigned long d_size; unsigned long b_addr; unsigned long b_size; unsigned long sz_addr; unsigned long s_size; unsigned long sp,fp,gp,ret,base; }; struct XF_HDR { char key[8]; /* "PS-X EXE" */ unsigned long text; unsigned long data; struct EXEC exec; char title[60]; /* "PlayStation(tm) Executable A1" */ }; #define EXE_HEAD_BYTES 2048 /*------- a.out file format --------*/ /* #define NEEDSWAP */ struct section_type { long flags; char name[ 8 ]; }; static struct section_type section_types[] = { (long)STYP_TEXT, {_TEXT}, (long)STYP_RDATA, {_RDATA}, (long)STYP_DATA, {_DATA}, (long)STYP_SDATA, {_SDATA} }; #define N_SECTION_TYPES (sizeof section_types / \ sizeof(struct section_type )) static xswab(char *from, char *to, int nbytes); static unsigned long swai(unsigned long i); static unsigned short swas(short i); static int is_need_load(struct scnhdr *s); struct scnhdr *readaouthead(FILE *fp, int *nsect, unsigned long *pc_value, unsigned long *gp_value); /***************************************************************** * s-format/exe/a.out file check routine * * return code: SFMT, EXEF, AOUTF, UNKF */ int filetype(char *file) { FILE *infile; char hbuf[10]; if( ( infile = fopen(file, "rb") ) == NULL) { dispf("Can't open \"%s\"\n\r",file); return UNKF; } fread( hbuf, 8, 1, infile); fclose(infile); if( hbuf[0] == 'S' && isdigit(hbuf[1]) ) return SFMT; if( strncmp(hbuf,"PS-X EXE",8) == 0 ) return EXEF; if( hbuf[1] == (MIPSELMAGIC/0x100) && hbuf[0] == (MIPSELMAGIC&0xff) ) return AOUTF; return UNKF; } /***************************************************************** * s-format file download to psx * * return code: OK or NG */ int xfersfmt(char *file, int verbose) { char line[CHRBUFMAX], *lp; long totalsize; int lcnt = 0; int timeout; time_t starttime; time_t laptime; FILE *fp; DWORD bytesRead; fp = fopen(file,"r"); if( fp == NULL ) { dispf("\"%s\" can't open\n\r",file); put_cmd_port(3); /* break to PSX */ return NG; } fseek(fp,0L,SEEK_END); totalsize = ftell(fp); fseek(fp,0L,SEEK_SET); lp = fgets(line, CHRBUFMAX, fp); /* get first line */ if( lp != NULL && line[0] == 'S' ) { prompt_catch_flag = 0; /*????*/ put_cmd_port('G'); put_cmd_port('\n'); starttime = time(NULL); laptime = time(NULL); do { while( *lp ) { put_cmd_port(*lp++); } /* put line */ if( lcnt > 0 && (lcnt % 0x20) == 0 ) { if( verbose ) dispf("%d line(%ld%%)",lcnt, ftell(fp)*100L/totalsize); laptime = time(NULL); } for( lp = "N\n" , timeout = 0 ; *lp ; timeout ++) { /* wait 'N\n' */ int inch = -1; ReadFile(hFile, (LPVOID)&inch, 1, &bytesRead, NULL); scan_cmd_port(); if(inch == *lp ) { lp++; continue; } if( inch >= 0 ) dispch(inch); if( keyhit() ) getkey(); /* eat key in */ if( timeout > 5000 ) { timeout = 0; if( time(NULL)-laptime > 4 ) { disps("\n\rxfersfmt:timeout !\n\r"); breakflag = 1; } } if( ctrlcflag || breakflag ) break; } if( (lcnt % 0x20) == 0 ) disps("\r"); lcnt ++; lp = fgets(line, CHRBUFMAX, fp); /* get next line */ } while( lp != NULL && ! ctrlcflag && ! breakflag ); if( ctrlcflag || breakflag ) { dispf(" \"%s\" %d sent\n\r send abort\n\r",file, lcnt); ctrlcflag = 0; breakflag = 0; goto errorend; } else if( ferror(fp) ) { dispf(" \"%s\" %d sent\n\r send error :%s\n\rabort !\n\r", file, lcnt, strerror(errno)); goto errorend; } else if( verbose ) { dispf("\r%d lines, %d sec.", lcnt ,time(NULL)-starttime); dispf("\n\r\"%s\" send ",file); } } else { dispf("\"%s\" is not S-format file\n\r",file); goto errorend; } fclose(fp); return OK; errorend: put_cmd_port(3); /* break to PSX */ fclose(fp); return NG; } /***************************************************************** * binary file download to psx * * return code: OK or NG */ int bload(char *file, unsigned long addr) { time_t starttime; register unsigned long i,len; FILE *infile; printf( "dload [%s]\n", file ); if( ( infile = fopen(file, "rb") ) == NULL) { dispf("Can't open \"%s\"\n\r",file); return NG; } /* Get length of the file */ prompt_catch_flag = 0; /*???*/ fseek(infile,0L,SEEK_END); len = ftell(infile); fseek(infile,0L,SEEK_SET); dispf("%s address:%08lx-%08lx size:%06lx ",file,addr,addr+len-1,len); if( fifo_memset_cmd(addr, len) != OK ) { fclose(infile); return NG; } starttime = time(NULL); if( !ctrlcflag && !breakflag ) { int rdsize; for( i = 0 ; i < len && !ctrlcflag && !breakflag ; i += rdsize ) { if( i+DATABUFSIZE < len ) { rdsize = fread(databuf, 1, DATABUFSIZE, infile); } else { rdsize = fread(databuf, 1, (size_t)(len-i), infile); } fifosend( databuf, rdsize ); dispf("%06lx:%5dsec.\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i+rdsize, time(NULL)-starttime ); } disps("\r\n"); } fclose(infile); if( !ctrlcflag && !breakflag ) return OK; else return NG; } /***************************************************************** * psx exe file download * * return code: OK or NG */ int loadexe(char *file, int verbose) { time_t starttime; register unsigned long i,len; unsigned long addr, regpc, reggp, regsp ; struct XF_HDR header; FILE *infile; if( ( infile = fopen(file, "rb") ) == NULL) { dispf("Can't open \"%s\"\n\r",file); return NG; } /*---- get exe header ----*/ if(fread(&header,1,sizeof(struct XF_HDR),infile) != sizeof(struct XF_HDR)) { dispf("\"%s\" header read error\n",file); fclose(infile); return NG; } if( fseek(infile, (long)EXE_HEAD_BYTES , SEEK_SET ) != 0 ) { dispf("\"%s\" header skip error\n",file); fclose(infile); return NG; } regpc = header.exec.pc0; reggp = header.exec.gp0; if( header.exec.sz_addr + header.exec.s_size != 0 ) regsp = header.exec.sz_addr + header.exec.s_size; else regsp = 0x801ffff0L; prompt_catch_flag = 0; /*???*/ /*---- Get length of the file ----*/ len = header.exec.t_size; addr = header.exec.t_addr; if( verbose ) dispf("%s address:%08lx-%08lx size:%06lx ", file, addr, addr+len-1, len); if( fifo_memset_cmd(addr, len) != OK ) { fclose(infile); return NG; } starttime = time(NULL); if( !ctrlcflag && !breakflag ) { int rdsize; for( i = 0 ; i < len && !ctrlcflag && !breakflag ; i += rdsize ) { if( i+DATABUFSIZE < len ) { rdsize = fread(databuf, 1, DATABUFSIZE, infile); } else { rdsize = fread(databuf, 1, (size_t)(len-i), infile); } fifosend( databuf, rdsize ); if( verbose ) dispf("%06lx:%5dsec.\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i+rdsize, time(NULL)-starttime ); } if( verbose ) disps("\r\n"); } fclose(infile); quit_smon(); if( !ctrlcflag && !breakflag ) { if( verbose ) dispf(" PC=%08lx, GP=%08lx, SP=%08lx\r\n", regpc, reggp, regsp); fifo_set_reg(R_EPC, regpc); fifo_set_reg(R_GP, reggp); fifo_set_reg(R_SP, regsp); return OK; } else return NG; } /***************************************************************** * a.out file download to psx * * return code: OK or NG */ int loadaout(char *file, int verbose) { time_t starttime; register unsigned long i,len; unsigned long addr, regpc, reggp, regsp ; struct scnhdr *section; int secidx, nsect; FILE *infile; /*--- file open ---*/ if( ( infile = fopen(file, "rb") ) == NULL) { dispf("Can't open \"%s\"\n\r",file); return NG; } /*--- read file header ---*/ section = readaouthead(infile, &nsect, ®pc, ®gp); regsp = 0x801ffff0; starttime = time(NULL); /*---- load memory image ----*/ for(secidx = 0; secidx < nsect; secidx ++ ) { if( is_need_load(§ion[secidx]) ){ fseek( infile, section[secidx].s_scnptr, SEEK_SET); addr = section[secidx].s_paddr; len = section[secidx].s_size; if( verbose ) dispf("%s [%6s] address:%08lx-%08lx size:%06lx ", file, section[secidx].s_name, addr, addr+len-1, len); if( fifo_memset_cmd(addr, len) != OK ) { fclose(infile); return NG; } if( !ctrlcflag && !breakflag ) { int rdsize; for( i = 0 ; i < len && !ctrlcflag && !breakflag ; i += rdsize ) { if( i+DATABUFSIZE < len ) { rdsize = fread(databuf, 1, DATABUFSIZE, infile); } else { rdsize = fread(databuf, 1, (size_t)(len-i), infile); } fifosend( databuf, rdsize ); if( verbose ) dispf("%06lx:%5dsec.\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i+rdsize, time(NULL)-starttime ); } if( verbose ) disps("\r\n"); } else { if( verbose ) dispf("%s [%6s] address:%08lx-%08lx size:%06lx skip\n\r", file, section[secidx].s_name, addr, addr+len-1, len); } } if( ctrlcflag || breakflag ) { break; } } free(section); fclose(infile); quit_smon(); if( !ctrlcflag && !breakflag ) { if( verbose ) dispf(" PC=%08lx, GP=%08lx, SP=%08lx\r\n", regpc, reggp, regsp); fifo_set_reg(R_EPC, regpc); fifo_set_reg(R_GP, reggp); fifo_set_reg(R_SP, regsp); return OK; } else return NG; } struct scnhdr *readaouthead(FILE *fp, int *nsect, unsigned long *pc_value, unsigned long *gp_value) { /* Mips Object File data structures */ struct filehdr file_header; struct aouthdr optional_header; struct scnhdr *section; if ( fread( (char *)&file_header, sizeof( struct filehdr ), 1, fp) != 1 ) { dispf("Error! file header can not read\n" ); return (struct scnhdr *)NG; } /* Read optional header if consistent */ if (file_header.f_opthdr != sizeof(struct aouthdr) ) { dispf("Error! file and optional headers inconsistent\n" ); return (struct scnhdr *)NG; } if( !(file_header.f_flags & F_EXEC) ) { dispf("Error! file is not executable \n" ); return (struct scnhdr *)NG; } if (fread( (char *)&optional_header, sizeof(struct aouthdr ), 1, fp) != 1 ) return (struct scnhdr *)NG; *nsect = file_header.f_nscns; *gp_value = optional_header.gp_value; *pc_value = optional_header.entry; section = malloc(sizeof(struct scnhdr)*file_header.f_nscns); if( section == NULL ) { dispf("Error! file section header table cannot allocate\n" ); return (struct scnhdr *)NG; } if (fread( (char *)section, sizeof(struct scnhdr)*file_header.f_nscns, 1, fp ) != 1 ) { dispf("Error! file section headers can not read\n" ); return (struct scnhdr *)NG; } return section; } static int is_need_load(struct scnhdr *s) { int i; for( i = 0 ; i < N_SECTION_TYPES; i++ ) { if ( s->s_flags & section_types[ i ].flags && !strcmp( s->s_name, section_types[i].name)) { return 1; } } return 0; }