/*-------------------------------------------------------------------------------------*\ $Header: //avm-fs01/Entwicklung/Basis/Generierung/AR7/filesystem.generation/avm-src/tffs-test/rcs/flashtest.c 1.1 2003/11/24 14:49:05Z mpommerenke Exp $ $Id: flashtest.c 1.1 2003/11/24 14:49:05Z mpommerenke Exp $ $Log: flashtest.c $ Revision 1.1 2003/11/24 14:49:05Z mpommerenke Initial revision \*-------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include "tffs.h" #include #define DEFINE_CRC32_TABLE #include "crc32-8.h" /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define RUN_CLOCK_VERSION 2 /*--- #define DEBUG ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if defined(DEBUG) #define DBG(a) { printf a ; fflush(stdout); } #else /*--- #if defined(DEBUG) ---*/ #define DBG(a) #endif /*--- #else ---*/ /*--- #if defined(DEBUG) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _run_clock_hours { unsigned int bits; } clock_hours; struct _run_clock_days { unsigned int bits; } clock_days; struct _run_clock_mounths { unsigned int bits; } clock_mounths; struct _run_clock_years { unsigned int bits; } clock_years; struct _run_clock_start_major { unsigned int bits[2]; } clock_restart_major; struct _run_clock_start_minor { unsigned int bits; } clock_restart_minor; char *program; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void init_value(void *buffer, unsigned int size) { DBG(("init_value(%u bytes)\n", size)); memset(buffer, 0xFF, size); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int bits_unset(unsigned char *ptr, unsigned int max_bits) { unsigned count; unsigned unset = 0; DBG(("bits_unset(%u max_bits):", max_bits)); while(max_bits) { for(count = 0 ; count < 8 ; count++, max_bits--) { if(*ptr & (1 << count)) { DBG((" unset=%u\n", unset)); return unset; } unset++; } ptr++; } DBG((" unset=%u (empty)\n", unset)); return unset; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void unset_next_bit(unsigned char *ptr, unsigned int max_bits) { unsigned count; DBG(("unset_next_bit(%u max_bits):", max_bits)); /*--- DBG(("*ptr: 0x%08x\n", *(unsigned int *)ptr)); ---*/ while(max_bits) { for(count = 0 ; count < 8 ; count++, max_bits--) { if(*ptr & (1 << count)) { *ptr &= ~(1 << count); DBG((" %u left\n", max_bits)); return; } } ptr++; } DBG((" error: all unset\n")); return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void korr_boot(char *device) { char Version[4]; int fd_read, fd_write; fd_read = tffs_open(O_RDONLY); if(fd_read < 0) return; fd_write = tffs_open(O_WRONLY); if(fd_write < 0) { tffs_close(fd_read); return; } if(tffs_read_value(fd_read, FLASH_FS_VERSION_COUNTER, Version, sizeof(Version)) == 0) { /*--- keine Version vorhanden ---*/ goto do_korr_boot; } if(*((unsigned int *)Version) == RUN_CLOCK_VERSION) { tffs_close(fd_read); tffs_close(fd_write); return; /*--- schon neue Version ---*/ } do_korr_boot: *((unsigned int *)Version) = RUN_CLOCK_VERSION; DBG(("korr_boot(%s): version=%u\n", device, *((unsigned int *)Version))); tffs_write_value(fd_write, FLASH_FS_VERSION_COUNTER, Version, sizeof(Version)); if(tffs_read_value(fd_read, FLASH_FS_REBOOT_MINOR, &clock_restart_minor, sizeof(clock_restart_minor)) == 0) { tffs_close(fd_read); tffs_close(fd_write); DBG(("korr_boot(%s): error kein minor\n", device)); return; /*--- kein MINOR Wert vorhanden, nichts zu korrigieren ---*/ } if(bits_unset((unsigned char *)&clock_restart_minor, 32) == 32) { unsigned int i; if(tffs_read_value(fd_read, FLASH_FS_REBOOT_MAJOR, &clock_restart_major, sizeof(clock_restart_major)) == 0) { tffs_close(fd_read); tffs_close(fd_write); DBG(("korr_boot(%s): error kein major\n", device)); return; /*--- kein MAJOR Wert vorhanden, nichts zu korrigieren ---*/ } i = bits_unset((unsigned char *)&clock_restart_minor, 32) + bits_unset((unsigned char *)&clock_restart_major, 64); DBG(("korr_boot(%s): %u reboots\n", device, i)); init_value(&clock_restart_minor, sizeof(clock_restart_minor)); init_value(&clock_restart_major, sizeof(clock_restart_major)); DBG(("korr_boot(%s): minor=%u\n", device, i % 32)); while(i % 32) { unset_next_bit((unsigned char *)&clock_restart_minor, 32); i--; } i /= 32; DBG(("korr_boot(%s): major=%u\n", device, i)); while(i) { unset_next_bit((unsigned char *)&clock_restart_major, 64); i--; } tffs_write_value(fd_write, FLASH_FS_REBOOT_MAJOR, &clock_restart_major, sizeof(clock_restart_major)); tffs_write_value(fd_write, FLASH_FS_REBOOT_MINOR, &clock_restart_minor, sizeof(clock_restart_minor)); } tffs_close(fd_read); tffs_close(fd_write); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void write_boot(char *device) { int fd_read, fd_write; fd_read = tffs_open(O_RDONLY); if(fd_read < 0) return; fd_write = tffs_open(O_WRONLY); if(fd_write < 0) { tffs_close(fd_read); return; } DBG(("write_boot(%s)\n", device)); if(tffs_read_value(fd_read, FLASH_FS_REBOOT_MINOR, &clock_restart_minor, sizeof(clock_restart_minor)) == 0) { init_value(&clock_restart_minor, sizeof(clock_restart_minor)); } unset_next_bit((unsigned char *)&clock_restart_minor, 32); if(bits_unset((unsigned char *)&clock_restart_minor, 32) == 32) { init_value(&clock_restart_minor, sizeof(clock_restart_minor)); if(tffs_read_value(fd_read, FLASH_FS_REBOOT_MAJOR, &clock_restart_major, sizeof(clock_restart_major)) == 0) { init_value(&clock_restart_major, sizeof(clock_restart_major)); } unset_next_bit((unsigned char *)&clock_restart_major, 64); tffs_write_value(fd_write, FLASH_FS_REBOOT_MAJOR, &clock_restart_major, sizeof(clock_restart_major)); } tffs_write_value(fd_write, FLASH_FS_REBOOT_MINOR, &clock_restart_minor, sizeof(clock_restart_minor)); tffs_close(fd_read); tffs_close(fd_write); return ; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void check_debug_cfg(void) { int fd = open("/var/flash/debug.cfg", O_RDONLY); if(fd > 0) { int fd_write; int dirty = 1; close(fd); fd_write = tffs_open(O_WRONLY); if(fd_write < 0) { return; } tffs_write_value(fd_write, 0x57, &dirty, sizeof(dirty)); tffs_close(fd_write); } return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void every_hour(char *device) { int fd_read, fd_write; fd_read = tffs_open(O_RDONLY); if(fd_read < 0) return; fd_write = tffs_open(O_WRONLY); if(fd_write < 0) { tffs_close(fd_read); return; } DBG(("every_hour(%s)\n", device)); /*--- Stunden ---*/ if(tffs_read_value(fd_read, FLASH_FS_HOUR_COUNTER, &clock_hours, sizeof(clock_hours)) == 0) { init_value(&clock_hours, sizeof(clock_hours)); } unset_next_bit((unsigned char *)&clock_hours, 24); /*--- sind Stunden voll, wenn ja dann zurücksetzen ---*/ if(bits_unset((unsigned char *)&clock_hours, 24) == 24) { init_value(&clock_hours, sizeof(clock_hours)); /*--- Tage ---*/ if(tffs_read_value(fd_read, FLASH_FS_DAY_COUNTER, &clock_days, sizeof(clock_days)) == 0) { init_value(&clock_days, sizeof(clock_days)); } unset_next_bit((unsigned char *)&clock_days, 31); /*--- sind Tage voll, wenn ja zurücksetzen ---*/ if(bits_unset((unsigned char *)&clock_days, 31) == 31) { init_value(&clock_days, sizeof(clock_days)); /*--- Monate ---*/ if(tffs_read_value(fd_read, FLASH_FS_MOUNTH_COUNTER, &clock_mounths, sizeof(clock_mounths)) == 0) { init_value(&clock_mounths, sizeof(clock_mounths)); } unset_next_bit((unsigned char *)&clock_mounths, 12); /*--- sind Monate voll, wenn ja zurücksetzen ---*/ if(bits_unset((unsigned char *)&clock_mounths, 12) == 12) { init_value(&clock_mounths, sizeof(clock_mounths)); /*--- Jahre (laufen nie über) ---*/ if(tffs_read_value(fd_read, FLASH_FS_YEAR_COUNTER, &clock_years, sizeof(clock_years)) == 0) { init_value(&clock_years, sizeof(clock_years)); } unset_next_bit((unsigned char *)&clock_years, 12); tffs_write_value(fd_write, FLASH_FS_YEAR_COUNTER, &clock_years, sizeof(clock_years)); } tffs_write_value(fd_write, FLASH_FS_MOUNTH_COUNTER, &clock_mounths, sizeof(clock_mounths)); } tffs_write_value(fd_write, FLASH_FS_DAY_COUNTER, &clock_days, sizeof(clock_days)); } tffs_write_value(fd_write, FLASH_FS_HOUR_COUNTER, &clock_hours, sizeof(clock_hours)); tffs_close(fd_write); tffs_close(fd_read); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void clear_all(char *device) { int fd; fd = tffs_open(O_WRONLY); if(fd < 0) return; DBG(("clear_all(%s)\n", device)); tffs_clear_value(fd, FLASH_FS_YEAR_COUNTER); tffs_clear_value(fd, FLASH_FS_MOUNTH_COUNTER); tffs_clear_value(fd, FLASH_FS_DAY_COUNTER); tffs_clear_value(fd, FLASH_FS_HOUR_COUNTER); tffs_clear_value(fd, FLASH_FS_REBOOT_MAJOR); tffs_clear_value(fd, FLASH_FS_REBOOT_MINOR); tffs_close(fd); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cleanup_all(char *device) { int fd; fd = tffs_open(O_WRONLY); if(fd < 0) return; DBG(("cleanup_all(%s)\n", device)); tffs_cleanup(fd); tffs_close(fd); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int htoi(char *p) { unsigned int value = 0; if(*p == '0' && (p[1] == 'x' || p[1] == 'X')) { if(!p || !*p) return value; if(*p == '0') p++; if(!p || !*p) return value; if(*p == 'x') p++; for( ;; ) { if(!p || !*p) return value; value <<= 4; if(*p >= '0' && *p <= '9') value |= *p - '0'; else if(*p >= 'a' && *p <= 'f') value |= *p - 'a' + 10; else if(*p >= 'A' && *p <= 'F') value |= *p - 'A' + 10; else break; p++; } return value; } return atoi(p); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static char *get_env(char *env[], char *name) { unsigned int i = 0, len; char *ptr; len = strlen(name); while(env[i]) { DBG(("env[%u]=\"%s\"\n", i, env[i])); if(!strncmp(env[i], name, len)) { ptr = strchr(env[i], '='); if(ptr) ptr++; return ptr; } i++; } return NULL; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ char *read_hidden_oem(char *device) { static char Buffer[64]; int fd; fd = tffs_open(O_RDONLY); if(fd < 0) { DBG(("%s: open device %s failed\n", program, device)); return NULL; } if(tffs_read_value(fd, FLASH_FS_RESERVED_COUNTER, Buffer, sizeof(Buffer))) { tffs_close(fd); return Buffer; } tffs_close(fd); Buffer[0] = '\0'; return NULL; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ char *read_dirty_flag(char *device) { static char Buffer[64]; int fd; fd = tffs_open(O_RDONLY); if(fd < 0) { DBG(("%s: open device %s failed\n", program, device)); return NULL; } if(tffs_read_value(fd, 0x57, Buffer, sizeof(Buffer))) { tffs_close(fd); return Buffer; } tffs_close(fd); Buffer[0] = '\0'; return NULL; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ char *read_rc_user_oem(char *device) { static char Buffer[64]; int fd; fd = tffs_open(O_RDONLY); if(fd < 0) { DBG(("%s: open device %s failed\n", program, device)); return NULL; } if(tffs_read_value(fd, FLASH_FS_ID_RC_USER, Buffer, sizeof(Buffer))) { tffs_close(fd); return Buffer; } tffs_close(fd); Buffer[0] = '\0'; return NULL; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int write_hidden_oem(char *device, char *oem) { int fd; fd = tffs_open(O_WRONLY); if(fd < 0) { DBG(("%s: open device %s failed\n", program, device)); return -1; } if(tffs_write_value(fd, FLASH_FS_RESERVED_COUNTER, oem, strlen(oem) + 1)) { tffs_close(fd); return 0; } tffs_close(fd); return -2; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int main(int argc, char* argv[], char *env[]) { unsigned int count; unsigned int demon = 0; unsigned int reinit = 0; unsigned int service = 0; char *oem, *hidden_oem; char *device = NULL; int fd; unsigned int sleep_value = 60 * 60; program = argv[0]; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ for(count = 1 ; count < argc ; count++) { if(argv[count][0] == '-') { switch(argv[count][1]) { case 'h': puts("use: "); puts(argv[0]); puts(" [-h(elp)][-i][-d(emon)][-r] -c "); puts("\t-h\tthis help"); puts("\t-d\tstart as demon"); puts("\t-i\tinit, reset all counters"); puts("\t-r\trecover tffs (cleanup)"); puts("\t-c\tdevice of tffs"); puts("\t-s\tsleep value (for test purpose)"); puts("\t-S\tService Code"); exit(-1); break; case 'd': demon = 1; break; case 'c': device = argv[++count]; tffs_device(device); break; case 's': sleep_value = htoi(argv[++count]); break; case 'i': reinit = 1; break; case 'r': reinit = 2; break; case 'S': service = 1; } } } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ switch(reinit) { case 1: clear_all(device); return 0; case 2: cleanup_all(device); return 0; default: break; } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ korr_boot(device); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ oem = get_env(env, "OEM="); hidden_oem = read_hidden_oem(device); if(hidden_oem == NULL) { write_hidden_oem(device, oem); } hidden_oem = read_hidden_oem(device); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if(demon == 1) { int pid = fork(); if(pid == 0) { /*-- child ---*/ close(0); #if !defined(DEBUG) close(1); #endif /*--- #if !defined(DEBUG) ---*/ close(2); write_boot(device); check_debug_cfg(); for( ;; ) { sleep(sleep_value); /*--- eine Stunde schlafen ---*/ every_hour(device); } } if(pid > 0) { puts("run_clock demon started\n"); return 0; } puts("run_clock demon start failed\n"); return 0; } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ fd = tffs_open(O_RDONLY); if(fd < 0) { DBG(("%s: open device %s failed\n", program, device)); return -1; } if(tffs_read_value(fd, FLASH_FS_HOUR_COUNTER, &clock_hours, sizeof(clock_hours)) == 0) { init_value(&clock_hours, sizeof(clock_hours)); } if(tffs_read_value(fd, FLASH_FS_DAY_COUNTER, &clock_days, sizeof(clock_days)) == 0) { init_value(&clock_days, sizeof(clock_days)); } if(tffs_read_value(fd, FLASH_FS_MOUNTH_COUNTER, &clock_mounths, sizeof(clock_mounths)) == 0) { init_value(&clock_mounths, sizeof(clock_mounths)); } if(tffs_read_value(fd, FLASH_FS_YEAR_COUNTER, &clock_years, sizeof(clock_years)) == 0) { init_value(&clock_years, sizeof(clock_years)); } if(tffs_read_value(fd, FLASH_FS_REBOOT_MAJOR, &clock_restart_major, sizeof(clock_restart_major)) == 0) { init_value(&clock_restart_major, sizeof(clock_restart_major)); } if(tffs_read_value(fd, FLASH_FS_REBOOT_MINOR, &clock_restart_minor, sizeof(clock_restart_minor)) == 0) { init_value(&clock_restart_minor, sizeof(clock_restart_minor)); } tffs_close(fd); if(service) { int i = 0; char *Name = NULL; char *Annex = "B"; int fd; int dirty; unsigned int crc32 = 0xFFFFFFFF; char Buffer[512]; fd = open("/dev/mtdblock/0", O_RDONLY); if(fd < 0) { fd = open("/dev/mtdblock2", O_RDONLY); } if(fd < 0) { fprintf(stderr, "[%s] error reading filesystem\n", argv[0]); } else { for( ;; ) { int n; i = read(fd, Buffer, sizeof(Buffer)); if(i <= 0) break; for(n = 0 ; n < i ; n++) crc32 = DoCrc32_8(crc32, Buffer[n]); } close(fd); } Annex = get_env(env, "ANNEX="); Name = get_env(env, "CONFIG_PRODUKT_NAME="); printf("%s-%s-%02u%02u%02u-%02u%02u%02u-%06o-%06o", Name ? Name : "Fritz!Box unbekannt", Annex, bits_unset((unsigned char *)&clock_hours, 24), bits_unset((unsigned char *)&clock_days, 31), bits_unset((unsigned char *)&clock_mounths, 12), bits_unset((unsigned char *)&clock_years, 32), bits_unset((unsigned char *)&clock_restart_major, 64), bits_unset((unsigned char *)&clock_restart_minor, 32), crc32 >> 14, crc32 & ((1 << 18) - 1) ); Name = read_rc_user_oem(device); if(Name == NULL) dirty = 'N'; /*--- N: 0x4E := 0100 1110 dirty: 0x04 = 14 ---*/ else if(strlen(Name) < 10) dirty = 'S'; /*--- S: 0x53 := 0101 0011 dirty: 0x13 = 19 ---*/ else dirty = 'U'; /*--- S: 0x55 := 0101 0101 dirty: 0x15 = 21 ---*/ if(read_dirty_flag(device)) dirty &= ~0x40; printf("-%02u", dirty); /* U = 0x55 := 0101 0101*/ /*--- printf("\noem='%s'\n", oem); ---*/ /*--- printf("hidden_oem='%s'\n", hidden_oem); ---*/ if(!strcmp(oem, hidden_oem)) printf("%02u", 'O'); else printf("%02u", 'C'); printf("%02u", RUN_CLOCK_VERSION); /*--- printf("
0x%x\n", crc32 >> 14); ---*/ /*--- printf("
0x%x\n", crc32 & ((1 << 18) - 1)); ---*/ return 0; } printf("running: %u hours %u days %u months %u years (%u starts)\n", bits_unset((unsigned char *)&clock_hours, 24), bits_unset((unsigned char *)&clock_days, 31), bits_unset((unsigned char *)&clock_mounths, 12), bits_unset((unsigned char *)&clock_years, 32), (bits_unset((unsigned char *)&clock_restart_major, 64) * 32) + bits_unset((unsigned char *)&clock_restart_minor, 32)); return 0; }