📄 rpl8.cpp
字号:
#if 0## The code is in public domain, May-September 2002.## RICOH Program Loader 8 (primarily DVD+RW units) for Linux 2.4 and# upwards. So far has been tested with:# - HP dvd100i# - Ricoh MP5120A# - Philips DVDRW208# - HP dvd200i## This is second version adding support for Program Loader 9 and# firmware consistency check.## The program never updates Program Loader code so that you should# always be able to downgrade your firmware in case something goes# wrong.## - make sure you have no media in drive, optionally go to single user# mode;# - run 'rpl8 /dev/cdrom firmware.image.bin';# - observe the program backing up your current firmware and uploading# new one;# - take system down and cycle the power;## There is -dump-only option which only backs up firmware. Note that# you might have to cycle the power even after -dump-only.## "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted"# surrounded by other nasty messages logged on console is "normal."#/bin/sh << EOSMODNAME=\`expr "/$0" : '\(.*[^/]\)/*$' : '.*/\(..*\)' : '\(.*\)\..*$'\`case "`uname -s`" inSunOS) (set -x; g++ -fno-exceptions -O -o \$MODNAME "$0" -lvolmgt) ;;*) (set -x; g++ -fno-exceptions -O -o \$MODNAME "$0") ;;esacEOSexit#endif#if defined(__linux)#define _XOPEN_SOURCE 500#endif#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <sys/mman.h>#include <poll.h>#include <signal.h>#include "transport.hxx"#define BUFFER_BLOCK (16*1024)#define FIRMWARE_SIZE (1024*1024)#define MAGIC_OFFSET (32*1024)#if FIRMWARE_SIZE%BUFFER_BLOCK!=0#error "Invalid BUFFER_BLOCK"#endif#if MAGIC_OFFSET%BUFFER_BLOCK!=0#error "Invalid BUFFER_BLOCK"#endifint main (int argc,char *argv[]){ int fd,in,out,off,j; struct stat sb; char dump[64],*meaning; unsigned char *buffer,*firmware,sigfile[6],sigunit[6],ascq='\xFF'; struct { unsigned char type,skip[7]; char vendor[8],ident[16],revision[4]; } inq; Scsi_Command cmd; unsigned char *sense=cmd.sense(); if (argc<3) { fprintf (stderr,"usage: %s /dev/cdrom " "[-[dump-only]|firmware.bin]\n",argv[0]); return 1; } if ((fd=open ("/dev/zero",O_RDWR)) < 0) { fprintf (stderr,"unable to open(\"/dev/zero\"): "), perror(NULL); return 1; } buffer = (unsigned char *)mmap(NULL,BUFFER_BLOCK,PROT_READ|PROT_WRITE, MAP_PRIVATE,fd,0); if (buffer==MAP_FAILED) { fprintf (stderr,"unable to anonymously mmap %d bytes: ",BUFFER_BLOCK), perror (NULL); return 1; } close (fd); if (!cmd.associate(argv[1])) { fprintf (stderr,"%s: unable to open: ",argv[1]), perror (NULL); return 1; } cmd[0]=0x12; // INQUIRY cmd[4]=sizeof(inq); cmd[5]=0; if (cmd.transport(READ,(unsigned char *)&inq,sizeof(inq))) { perror("unable to INQUIRY, examine /var/log/message"); return 1; } if ((inq.type&0x1F) != 5) { fprintf (stderr,"\"%s\" is not a CD-ROM device\n",argv[1]); return 1; } cmd[0]=0x00; // TEST UNIT READY cmd[5]=0x80; if (!cmd.transport()) { fprintf (stderr,"\"%s\" is ready, is media present?\n",argv[1]); return 1; } if (sense[12] != 0x3A) // should reply with "NO MEDIA" { fprintf (stderr,"\"%s\": unexpected ASC=%02xh/ASCQ=%02xh\n", argv[1],sense[12],sense[13]); return 1; } sprintf (dump,"%.8s%.16s%.4s.bin",inq.vendor,inq.ident,inq.revision); for(j=0;dump[j];j++) if (dump[j]==' ') dump[j]='_'; in=-1, firmware=NULL; if (argv[2][0] != '-') { unsigned short cksum; int i; if ((in=open(argv[2],O_RDONLY)) < 0) { fprintf (stderr,"unable to open(\"%s\"): ",argv[2]), perror (NULL); return 1; } if (fstat(in,&sb) < 0) { fprintf (stderr,"unable to stat(\"%s\"): ",argv[2]), perror (NULL); return 1; } if (sb.st_size != FIRMWARE_SIZE) { fprintf (stderr,"\"%s\": size is insane\n",argv[2]); return 1; } firmware=(unsigned char *)mmap(NULL,FIRMWARE_SIZE,PROT_READ, MAP_PRIVATE,in,0); if (firmware==MAP_FAILED) { fprintf (stderr,"unable to mmap(\"%s\"): ",argv[2]), perror (NULL); return 1; } close (in); memcpy(sigfile,firmware+MAGIC_OFFSET+4,6); if (memcmp(sigfile,"MMP5",4)) { fprintf (stderr,"\"%s\": signature is insane\n",argv[2]); return 1; } for (cksum=0,i=MAGIC_OFFSET;i<FIRMWARE_SIZE-2;i++) cksum += firmware[i]; if ((cksum&0xFF) != firmware[FIRMWARE_SIZE-1] || (cksum>>8) != firmware[FIRMWARE_SIZE-2] ) { fprintf (stderr,"\"%s\" is corrupted or encrypted\n",argv[2]); return 1; } } if ((out=open(dump,O_WRONLY|O_CREAT|O_EXCL,0666)) < 0) { fprintf (stderr,"unable to creat(\"%s\"): ",dump), perror (NULL); return 1; } cmd[0]=0xE4; // INVOKE PROGRAM LOADER cmd[9]=(1<<6)&0x40; if (cmd.transport()) { fprintf (stderr,"\"%s\": unable to invoke RICOH Program Loader " "[ASC=%02xh/ASCQ=%02xh]\n", argv[1],sense[12],sense[13]); return 1; } do { // not really a loop, just a way to get rid of goto's... poll(NULL,0,250); cmd[0]=0xE4; // INVOKE PROGRAM LOADER cmd[9]=(1<<6)&0x40; if (cmd.transport()) { fprintf (stderr,"\"%s\"[E4]: unexpected ASC=%02xh/ASCQ=%02xh\n", argv[1],sense[12],sense[13]); break; } poll(NULL,0,250); cmd[0]=0x12; // INQUIRY cmd[4]=sizeof(inq); cmd[5]=0; if (cmd.transport(READ,(unsigned char *)&inq,sizeof(inq))) { perror("unable to INQUIRY, examine /var/log/message"); break; } if (memcmp(&inq.vendor,"RICOH Program Loader 8",24) && memcmp(&inq.vendor,"RICOH Program Loader 9",24) ) { fprintf (stderr,"\"%s\": unknown Program Loader " "%.8s|%.16s|%.4s\n", argv[1],inq.vendor,inq.ident,inq.revision); break; } fprintf (stderr,"\"%s\": dumping firmware image to \"%s\" ", argv[1],dump); for (off=0;off<FIRMWARE_SIZE;off+=BUFFER_BLOCK) { cmd[0]=0xE3; // DOWNLOAD FIRMWARE PAGE cmd[2]=(off>>24)&0xFF; cmd[3]=(off>>16)&0xFF; cmd[4]=(off>>8)&0xFF; cmd[5]=(off)&0xFF; cmd[7]=(BUFFER_BLOCK>>8)&0xFF; cmd[8]=(BUFFER_BLOCK)&0xFF; cmd[9]=0; if (cmd.transport(READ,buffer,BUFFER_BLOCK)) { fprintf (stderr,"\"%s\"[E3]: unexpected " "ASC=%02xh/ASCQ=%02xh\n", argv[1],sense[12],sense[13]); in=-1; break; } if (write(out,buffer,BUFFER_BLOCK) != BUFFER_BLOCK) { fprintf (stderr,"unable to write(\"%s\"): ",dump), perror(NULL); in=-1; break; } fprintf (stderr,"."); if (off==MAGIC_OFFSET) { memcpy(sigunit,buffer+4,6); } } fprintf (stderr,"\n"); if (in==-1) break; /* dump only or we failed to backup */#if 1 if (memcmp(sigunit,sigfile,6)) { fprintf (stderr,"\"%s\": firmware signature mismatch " "[%.6s|%.6s]\n", argv[1],sigunit,sigfile); break; }#endif fprintf (stderr,"\"%s\": uploading firmware image",argv[1]); for (off=0;off<FIRMWARE_SIZE;off+=BUFFER_BLOCK) { cmd[0]=0xE2; // UPLOAD FIRMWARE PAGE cmd[5]=(BUFFER_BLOCK>>16)&0xFF; cmd[6]=(BUFFER_BLOCK>>8)&0xFF; cmd[7]=(BUFFER_BLOCK)&0xFF; cmd[11]=0; if (cmd.transport(WRITE,firmware+off,BUFFER_BLOCK)) { fprintf (stderr,"\"%s\"[E2]: unexpected " "ASC=%02xh/ASCQ=%02xh\n", argv[1],sense[12],sense[13]); in=-1; break; } fprintf (stderr,"."); } fprintf (stderr,"\n"); if (in==-1) break; /* failed to upload */ fprintf (stderr,"\"%s\": unlocking firmware\n",argv[1]); cmd[0]=0xE0; // UNLOCK FIRMWARE cmd[3]=0; cmd[9]=0; if (cmd.transport()) { fprintf (stderr,"\"%s\"[E0]: unexpected " "ASC=%02xh/ASCQ=%02xh\n", argv[1],sense[12],sense[13]); break; } fprintf (stderr,"\"%s\":
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -