/* * This file is part of the LinuxBIOS project. * * Copyright (C) 2007 Reinder E.N. de Haan nospam-at-mveas-dot-com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ //#include //#include //#include //void hw_init(void); /* unsigned char uart_rx_1byte(void) { unsigned tmp; __asm__ __volatile__( " \nuart_dorx_1byte_wait: \n" " mov $1021 , %%dx\n" " inb %%dx, %%al\n" " test $1, %%al\n" " jz uart_dorx_1byte_wait\n" " mov $1016 , %%dx\n" " inb %%dx, %%al\n" : "=a" (tmp): : "esp", "edx"); return(tmp); } */ void delay_ms(unsigned short ms) { //unsigned short delay; while(ms) { // for(delay=0x780;delay;) // { // asm("nop"); // delay--; // } ms--; } } //void delay_us(unsigned short us) //{ // unsigned short delay; // while(us) // { // for(delay=2;delay;) // { // //asm("nop"); // delay--; // } // us--; // } //} unsigned char uart_do_rx_byte(void) { unsigned char tmp; // al = tmp // dx = port __asm__ __volatile__( " movl $uart_dorx_byte_ret,%%esi;\n" "uart_dorx_byte: \n" " mov %%dx , %%ax\n" " shl $10, %%eax\n" "uart_dorx_byte_wait: \n" " mov $1021 , %%dx\n" " inb %%dx, %%al\n" " test $1,%%al\n" " jz uart_dorx_byte_wait\n" " mov $1016 , %%dx\n" " inb %%dx, %%al\n" " mov %%ax,%%dx\n" " shr $10, %%eax\n" " xchg %%ax,%%dx\n" " jmp %%cs:(%%esi)\n" "uart_dorx_byte_ret: .long +4\n" : "=a" (tmp): : "esi"); //print_emerg_hex8(tmp); return(tmp); } unsigned char uart_rx_byte(void) { unsigned char tmp; asm(" movl $.+0xa,%%esi;\n" " jmp uart_dorx_byte\n" " .long .+4\n" : "=a" (tmp): : "esi"); return(tmp); } unsigned char uart_do_rx_2hex(void) { unsigned short tmp; // unsigned long retesp; // __asm__ __volatile__("\nuart_dorx_2hex: \n" :"=S" (retesp)::); // al = tmp // dx = port // ebx = ret // ecx = digits __asm__ __volatile__( " movl $uart_dorx_2hex_ret,%%esi;\n" "uart_dorx_2hex: \n" " mov $2 , %%ecx\n" " mov $0 , %%ebx\n" "uart_dorx_hex:\n" " mov %%dx , %%ax\n" " shl $10, %%eax\n" " dorx_hex_wait:\n" " mov $1021 , %%dx\n" " inb %%dx, %%al\n" " test $1,%%al\n" " jz dorx_hex_wait\n" " mov $1016 , %%dx\n" " inb %%dx, %%al\n" " cmp $48 , %%al\n" //<'0' " jl dorx_hex_wait\n" " cmp $102 , %%al\n" //>'f' " jg dorx_hex_wait\n" " cmp $57 , %%al\n" //<='9' OK " jng dorxh_09\n" " cmp $65 , %%al\n" //<'A' " jl dorx_hex_wait\n" " cmp $70 , %%al\n" //<='F' OK " jng dorxh_af\n" " cmp $97 , %%al\n" //<'a' " jl dorx_hex_wait\n" "dorxh_af:\n" " add $9 , %%al\n" "dorxh_09:\n" " and $15 , %%al\n" " shl $4 , %%ebx\n" " or %%al, %%bl\n" " loop dorx_hex_wait\n" " shr $10, %%eax\n" " mov %%ax,%%dx\n" " movl %%ebx, %%eax\n" " jmp %%cs:(%%esi)\n" "uart_dorx_2hex_ret: .long +4\n" : "=a" (tmp): : "esi","ebx","ecx"); //print_emerg_hex8(tmp); return(tmp); } unsigned char uart_rx_2hex(void) { unsigned char tmp; asm(" movl $.+0xa,%%esi;\n" " jmp uart_dorx_2hex\n" " .long .+4\n" : "=a" (tmp): : "esi","ebx","ecx"); return(tmp); } unsigned short uart_rx_4hex(void) { unsigned short tmp; asm(" mov $4 , %%ecx\n" " mov $0 , %%ebx\n" " movl $.+0xa,%%esi;\n" " jmp uart_dorx_hex\n" " .long .+4\n" : "=a" (tmp): : "esi","ebx","ecx"); return(tmp); } unsigned long uart_rx_8hex(void) { unsigned long tmp; asm(" mov $8 , %%ecx\n" " mov $0 , %%ebx\n" " movl $.+0xa,%%esi;\n" " jmp uart_dorx_hex\n" " .long .+4\n" : "=a" (tmp): : "esi","ebx","ecx"); return(tmp); } unsigned char read(unsigned long address) { return(*((unsigned char *) address)); } void mem_write(unsigned long address,unsigned char value) { __asm__ __volatile__( " movb %%al,(%%edi)\n" : : "D" (address), "a" (value)); } unsigned int flash_write(unsigned long address,unsigned char value) { unsigned short tmp; unsigned short timeout; // if(address > 0xF0000) // { // print_emerg("Error Prohibited address !!!! \r"); // return; // } // timeout=0xFF; __asm__ __volatile__( "movb $0x2e,(0xD5000)\n" "movb $0xF0,(0xE0000)\n" "movb $0xAA,(0xE0555)\n" "movb $0x55,(0xE02AA)\n" "movb $0xA0,(0xE0555)\n" "movb %%al,(%%esi)\n" "nop\nnop\nnop\nnop\n" // "movl %%ecx,%%eax\n" // "movl $0xF,%%ecx\n" // "loop .\n" // "movl %%eax,%%ecx\n" "movb (%%esi),%%al\n" "movb (%%esi),%%ah\n" :"=a"(tmp) :"a"(value),"S"(address)); // mem_write((address & ~0x7FFF)|0x0555,0xAA); // mem_write((address & ~0x7FFF)|0x02AA,0x55); // mem_write((address & ~0x7FFF)|0x0555,0xA0); // mem_write( address,value); // __asm__ __volatile__( // "movl $0xF,%%ecx\nloop .\n" // "movb (0xE0000),%%al\n" // "movb (0xE0000),%%ah\n" // :"=a"(tmp) : :"ecx"); timeout=0xff; while((((tmp & 0xFF) != ((tmp >>8) & 0xFF)) || ((tmp & 0xFF) != value)) && (--timeout != 0)) { //tmp = timeout; tmp--; timeout=tmp; // timeout--; //print_emerg_char('.'); __asm__ __volatile__( "nop\nnop\nnop\nnop\n" "movb (%%esi),%%al\n" "movb (%%esi),%%ah\n" :"=a"(tmp):"S"(address)); } __asm__ __volatile__("movb $0x2c,(0xD5000)\n"); __asm__ __volatile__("movb $0xF0,(0xE0000)\n"); if(timeout) { // print_emerg_char('-'); return 0; }else{ //print_emerg_char('-'); __asm__ __volatile__("movb $0x2d,(0xD5000)\n"); print_emerg_hex32(address); print_emerg(":FPE\r"); return 1; } } void erase(unsigned long address) { unsigned char tmp1,tmp2; unsigned short tmp,timeout=0x1000; print_emerg_char('['); // __asm__ __volatile__("movb $0x5e,(0xD5000)\n"); // mem_write((address & ~0x7FFF)|0x0555,0xF0);// mem_write((address & ~0x7FFF)|0x0555,0xAA); // mem_write((address & ~0x7FFF)|0x02AA,0x55);// mem_write((address & ~0x7FFF)|0x0555,0x80); // mem_write((address & ~0x7FFF)|0x0555,0xAA);// mem_write((address & ~0x7FFF)|0x02AA,0x55); // mem_write((address ),0x30); __asm__ __volatile__( "movb $0x5D,(0xD5000)\n" "movb $0xF0,(0xE0000)\n" "movb $0xAA,(0xE0555)\n" "movb $0x55,(0xE02AA)\n" "movb $0x80,(0xE0555)\n" "movb $0xAA,(0xE0555)\n" "movb $0x55,(0xE02AA)\n" "movb $0x30,(0xE0000)\n" "movl $0xFFFF,%%ecx\n" "loop .\n" "movb $0xA5,(0xD5000)\n" "movb (0xE0000),%%al\n" "movb (0xE0000),%%ah\n" :"=a"(tmp) : :"ecx"); tmp1 = (tmp>>8) & 0xff; // *((unsigned char *) address); tmp2 = tmp & 0xFF; //*((unsigned char *) address); while(((tmp1 != tmp2) || (tmp1 !=0xff)) && (timeout)) { __asm__ __volatile__( "movb (0xE0000),%%al\n" "movb (0xE0000),%%ah\n" :"=a"(tmp)); tmp1 = tmp>>8; // *((unsigned char *) address); tmp2 = tmp & 0xFF; //*((unsigned char *) address); timeout--; if(timeout==0) { __asm__ __volatile__("movb $0x5B,(0xD5000)\n"); __asm__ __volatile__("movb $0xF0,(0xE0000)\n"); //print_emerg_hex32(address); print_emerg(":EE\r"); // return; } } __asm__ __volatile__("movb $0x57,(0xD5000)\n"); __asm__ __volatile__("movb $0xF0,(0xE0000)\n" "movl $0xF,%%ecx\n" "loop .\n" : : :"ecx"); // print_emerg_char('}'); print_emerg_char(']'); return; } unsigned char download(unsigned char mode) { unsigned char len; unsigned char cmd; unsigned long offset=0; unsigned long haddress=0; unsigned long addr=0; unsigned char tmp; unsigned char tmp2; print_emerg("\rHex\r"); while(1) { // print_emerg_hex32(haddress); tmp='\r';//uart_rx_1byte(); print_emerg_char('<'); while((tmp & 0xFF) !=':') { if((tmp & 0xFF) !='\r') print_emerg_char(tmp); tmp=uart_rx_byte(); } print_emerg_char(';'); len=uart_rx_2hex(); offset=uart_rx_4hex(); // offset=uart_rx_2hex()<<8; // offset|=uart_rx_2hex(); cmd=uart_rx_2hex(); // print_emerg_hex32(haddress); // print_emerg_hex8(len); // print_emerg_hex16(offset); // print_emerg_hex8(cmd); if((len == 0) && (cmd==0x01)) { if (mode==0) print_emerg("DlOk\r"); else print_emerg("V.Ok\r"); return(0); }else if(cmd==0) { while(len) { addr=haddress+offset; //print_emerg_char('.'); // print_emerg_hex32(addr); // print_emerg_hex8(len); tmp=uart_rx_2hex(); if(mode==0) { if(flash_write(addr, tmp)!=0); { // print_emerg("FWF"); //return(1); // goto fwf; } } tmp2=read(addr); // delay_ms(100); if( (tmp2 != tmp) || (tmp2 !=read(addr)) || (tmp !=read(addr))) { print_emerg("PE@"); //fwf: print_emerg_hex32(addr); print_emerg_hex8(tmp); // print_emerg_char('='); // print_emerg_hex8(tmp2); print_emerg_hex8(read(addr)); // print_emerg_char('!'); // print_emerg_char('='); print_emerg_char('\r'); return(1); } offset++; // if (offset==0) // { // haddress += 0x10000; // } addr=haddress+offset; len--; } #if 1 }else if((cmd==4) && (len ==2)) { haddress=uart_rx_4hex(); haddress <<=16; addr=haddress+offset; // print_emerg_hex32(haddress); print_emerg_char('+'); #endif }else { print_emerg("E inv rec\r"); // cmd==0x"); return(1); // print_emerg_hex8(cmd); } // uart_rx_2hex(); print_emerg_char('!'); // print_emerg_hex32(haddress); } } #if 0 //const char LF[] = "\r"; const char version[] = \ "LinuxBios panicroom bootloader\r"; const char usage_txt[] = \ "I: Init\r" \ "H: Help\r" \ "R: Read: R AAAA\r" \ "U: Read Block: B AAAA LLLL\r" \ "W: Write: W AAAA VVVV\r" \ "P: Download Hex file\r" \ "V: verify\r" \ // "E: Erase sector\r" "X: Erase flash\r"; // "T: Take Bus\r" // "G: Give Bus\r" #endif void panic (void) { register unsigned char tmp=0; register unsigned char cmd=0; register unsigned long addr; // print_emerg(version); // print_emerg(usage_txt); __asm__ __volatile__("movb $0xFF,(0xD5000)\n"); while(1) { print_emerg_char('>'); tmp=uart_rx_byte(); cmd=tmp & 0x0DF; // print_emerg_hex8(cmd); switch(cmd) { // case 'I': // __vectors(); //reset // break; case 'H': //print_emerg(usage_txt); print_emerg("hi"); break; case 'I': __asm__ __volatile__( "movb $0xF0,(0xF0000)\n" "movb $0xAA,(0xF0555)\n" "movb $0x55,(0xF02AA)\n" "movb $0x90,(0xF0555)\n" "movb (0xF0000),%%al\n" "movb $0xF0,(0xF0000)\n" :"=a"(tmp)); print_emerg_hex8(tmp); __asm__ __volatile__( "movb $0xF0,(0xF0000)\n" "movb $0xAA,(0xF0555)\n" "movb $0x55,(0xF02AA)\n" "movb $0x90,(0xF0555)\n" "movb (0xF0001),%%al\n" "movb $0xF0,(0xF0000)\n" :"=a"(tmp)); print_emerg_hex8(tmp); break; case 'T': // tmp=uart_rx_2hex(); // __asm__ __volatile__( // " movb %%al,(0xD5000)\n" // : : "a" (tmp):); break; case 'R': addr=uart_rx_8hex(); // print_emerg_hex32(addr); print_emerg_hex8(read(addr)); break; // case 'Y': // for(tmp=0;tmp<0xff;tmp++) // { // if((tmp & 0xf)==0) // { // print_emerg_char('\r'); // print_emerg_hex8(tmp); // print_emerg_char(':'); // } // print_emerg_char(' '); // print_emerg_hex8(read(tmp)); // // } // break; case 'Q': addr=uart_rx_8hex(); flash_write(addr,uart_rx_2hex()); //print_emerg_hex8(read(addr)); break; case 'W': addr=uart_rx_8hex(); mem_write(addr,uart_rx_2hex()); print_emerg_hex8(read(addr)); break; case 'P': case 'V': //print_emerg("P/V"); //download(0); #define FBS 0 #if !FBS tmp=((cmd & 0x0DF)=='V')?1:0; print_emerg_char('A'+tmp); download(tmp); #endif break; // download(1); // break; case 'X': // erase(0x80000); // erase(0x90000); // erase(0xA0000); // erase(0xB0000); // erase(0xC0000); // erase(0xD0000); erase(0xE0000); // erase(0xF0000); break; case 'Z': #if FBS __asm__ __volatile__( "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0x80,(0xF0555)\n" "movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0x30,(0xF0000)\n movl $0x7FFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0xea,(0xFFFFFFF0)\n movl $0xFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0x00,(0xFFFFFFF1)\n movl $0xFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0x00,(0xFFFFFFF2)\n movl $0xFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0x00,(0xFFFFFFF3)\n movl $0xFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0xD4,(0xFFFFFFF4)\n movl $0xFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0x00,(0xFFFFFFF5)\n movl $0xFFF,%%ecx\n loop .\n" "movb $0xF0,(0xF0000)\n movb $0xAA,(0xF0555)\n movb $0x55,(0xF02AA)\n movb $0xA0,(0xF0555)\n" "movb $0x00,(0xFFFFFFF6)\n movl $0xFFF,%%ecx\n loop .\n" : : :"ecx"); print_emerg("boot jump done"); #endif break; case 'q': tmp=uart_do_rx_byte(); tmp=uart_do_rx_2hex(); // use this one only once break; // case 'T': // case 'G': // break; default: // print_emerg_hex8(cmd); // print_emerg_char('?'); print_emerg_char(cmd & 0xdf); break; } } return; }