rockbox/bootloader/main-ppsansawipe.c

248 lines
6.6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: main-e200r-installer.c 15599 2007-11-12 18:49:53Z amiconn $
*
* Copyright (C) 2011 by Frank Gevaerts
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "cpu.h"
#include "file.h"
#include "system.h"
#include "../kernel-internal.h"
#include "lcd.h"
#include "font.h"
#include "storage.h"
#include "button.h"
#include "disk.h"
#include <string.h>
#include "i2c.h"
#include "backlight-target.h"
#include "power.h"
unsigned char zero[1024*64];
unsigned char nonzero[1024*64];
unsigned char scratch[1024*64];
struct storage_info info;
int format_partition(int start, int size);
#define SPT 63
#define HPC 255
int c(int lba)
{
return lba/(SPT * HPC);
}
int h(int lba)
{
return (lba/SPT)%HPC;
}
int s(int lba)
{
return (lba%SPT) + 1;
}
int write_mbr(int datastart,int datasize, int firmwarestart, int firmwaresize)
{
unsigned char mbr[512];
memset(mbr,0,512);
mbr[446]=0x80; /* flags */
mbr[447]=h(datastart); /* chs1[0] (h) */
mbr[448]=s(datastart); /* chs1[1] (s) */
mbr[449]=c(datastart); /* chs1[2] (c) */
mbr[450]=0x0b; /* type */
mbr[451]=h(datastart+datasize-1); /* chs2[0] (h) */
mbr[452]=s(datastart+datasize-1); /* chs2[1] (s) */
mbr[453]=c(datastart+datasize-1); /* chs2[2] (c) */
mbr[454]=(datastart&0x000000ff); /* lba[0] */
mbr[455]=(datastart&0x0000ff00) >>8; /* lba[1] */
mbr[456]=(datastart&0x00ff0000) >>16; /* lba[2] */
mbr[457]=(datastart&0xff000000) >>24; /* lba[3] */
mbr[458]=(datasize&0x000000ff); /* size[0] */
mbr[459]=(datasize&0x0000ff00) >>8; /* size[1] */
mbr[460]=(datasize&0x00ff0000) >>16; /* size[2] */
mbr[461]=(datasize&0xff000000) >>24; /* size[3] */
mbr[462]=0; /* flags */
mbr[463]=h(firmwarestart); /* chs1[0] (h) */
mbr[464]=s(firmwarestart); /* chs1[1] (s) */
mbr[465]=c(firmwarestart); /* chs1[2] (c) */
mbr[466]=0x84; /* type */
mbr[467]=h(firmwarestart+firmwaresize-1); /* chs2[0] (h) */
mbr[468]=s(firmwarestart+firmwaresize-1); /* chs2[1] (s) */
mbr[469]=c(firmwarestart+firmwaresize-1); /* chs2[2] (c) */
mbr[470]=(firmwarestart&0x000000ffu); /* lba[0] */
mbr[471]=(firmwarestart&0x0000ff00u) >>8; /* lba[1] */
mbr[472]=(firmwarestart&0x00ff0000u) >>16; /* lba[2] */
mbr[473]=(firmwarestart&0xff000000u) >>24; /* lba[3] */
mbr[474]=(firmwaresize&0x000000ffu); /* size[0] */
mbr[475]=(firmwaresize&0x0000ff00u) >>8; /* size[1] */
mbr[476]=(firmwaresize&0x00ff0000u) >>16; /* size[2] */
mbr[477]=(firmwaresize&0xff000000u) >>24; /* size[3] */
mbr[510]=0x55;
mbr[511]=0xaa;
int res = storage_write_sectors(0,1,mbr);
if(res != 0)
{
return -1;
}
return 0;
}
/* Hack. We "steal" line from common.c to reset the line number
* so we can overwrite the previous line for nicer progress info
*/
extern int line;
int wipe(int size, int verify)
{
int i;
int res;
int sectors = sizeof(nonzero)/512;
for(i=0;i<size;i+=sectors)
{
if(verify)
{
res = storage_write_sectors(i,sectors,nonzero);
if(res != 0)
{
printf("write error (1) on sector %d (of %d)!",i,size);
return -1;
}
res = storage_read_sectors(i,sectors,scratch);
if(res != 0)
{
printf("read error (1) on sector %d (of %d)!",i,size);
return -1;
}
res = memcmp(nonzero, scratch, sizeof(nonzero));
if(res != 0)
{
printf("compare error (1) on sector %d (of %d)!",i,size);
return -1;
}
}
res = storage_write_sectors(i,sectors,zero);
if(res != 0)
{
printf("write error (2) on sector %d (of %d)!",i,size);
return -1;
}
if(verify)
{
res = storage_read_sectors(i,sectors,scratch);
if(res != 0)
{
printf("read error (2) on sector %d (of %d)!",i,size);
return -1;
}
res = memcmp(zero, scratch, sizeof(nonzero));
if(res != 0)
{
printf("compare error (2) on sector %d (of %d)!",i,size);
return -1;
}
}
if(i%2048 == 0)
{
printf("%d of %d MB done",i/2048, size/2048);
/* Hack to overwrite the previous line */
line--;
}
}
return 0;
}
void* main(void)
{
int i;
int btn;
system_init();
kernel_init();
lcd_init();
font_init();
button_init();
i2c_init();
backlight_hw_on();
lcd_set_foreground(LCD_WHITE);
lcd_set_background(LCD_BLACK);
lcd_clear_display();
btn = button_read_device();
verbose = true;
lcd_setfont(FONT_SYSFIXED);
printf("Sansa initialiser");
printf("");
i=storage_init();
disk_init(IF_MD(0));
storage_get_info(0,&info);
int size = info.num_sectors;
memset(zero,0,sizeof(zero));
memset(nonzero,0xff,sizeof(nonzero));
printf("Zeroing flash");
int res;
res = wipe(size, 0);
if(res != 0)
{
printf("error wiping flash");
}
int firmwaresize = 0xa000;
int firmwarestart = size - firmwaresize;
int datastart = 600;
int datasize = firmwarestart - datastart;
res = write_mbr(datastart,datasize,firmwarestart,firmwaresize);
if(res != 0)
{
printf("error writing mbr");
}
res = format_partition(datastart, datasize);
if(res != 0)
{
printf("error formatting");
}
printf("Wipe done.");
if (button_hold())
printf("Release Hold and");
printf("press any key to");
printf("shutdown.");
printf("Remember to use");
printf("manufacturing");
printf("mode to recover");
printf("further");
while(button_read_device() == BUTTON_NONE);
power_off();
return NULL;
}