/* * (C) Copyright 2015 * Alexander Couzens, lynxis@fe80.eu * * See file CREDITS for list of people who contributed to this * project. * * 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., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #ifdef CFG_CMD_BOOTCYCLE #ifndef MAX_REBOOTS #define MAX_REBOOTS 10 #endif #define SRAM_BOOT_CYCLE 0xbd000100 #define BOOT_CYCLE_MAGIC 0xfeedb00d #define BOOT_CYCLE_VERSION 1 struct sram_boot_cycle { uint32_t magic; uint32_t version; uint32_t counter; uint32_t crc; }; static int valid_boot_cycle(struct sram_boot_cycle *sram) { if (sram->magic != BOOT_CYCLE_MAGIC) return 0; if (sram->version != BOOT_CYCLE_VERSION) return 0; uint32_t crc = crc32(0xdeadbeef, (void *)sram, sizeof(*sram) - 4); if (crc != sram->crc) return 0; return 1; } static void reset_boot_cycle(struct sram_boot_cycle *sram) { sram->magic = BOOT_CYCLE_MAGIC; sram->version = BOOT_CYCLE_VERSION; sram->counter = 0; sram->crc = (uint32_t) crc32(0xdeadbeef, (void *)sram, sizeof(*sram) - 4); } void increase_boot_cycle(struct sram_boot_cycle *sram, uint32_t value) { if (!valid_boot_cycle(sram)) reset_boot_cycle(sram); sram->counter += value; sram->crc = (uint32_t) crc32(0xdeadbeef, (void *)sram, sizeof(*sram) - 4); } int do_inccycle(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { uint32_t value = 1; if (argc == 2) { int given_value = (int)simple_strtol(argv[1], NULL, 10); if (given_value > 0) { value = given_value; } else { printf("Ignoring invalid argument %s\n", argv[1]); } } increase_boot_cycle((void *) SRAM_BOOT_CYCLE, value); return CMD_RET_SUCCESS; } int do_resetcycle(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { reset_boot_cycle((void *) SRAM_BOOT_CYCLE); return CMD_RET_SUCCESS; } /* report failure when we need to go to rescue */ int do_checkcycle(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { uint32_t threshold = MAX_REBOOTS; if (argc == 2) { int given_threshold = (int)simple_strtol(argv[1], NULL, 10); if (given_threshold > 0) { threshold = given_threshold; } else { printf("Ignoring invalid argument %s\n", argv[1]); } } struct sram_boot_cycle *sram = (void *) SRAM_BOOT_CYCLE; /* when called we should ever have a valid boot cycle entry * if it's invalid we have most likely a broken bootloader or hw? */ if (!valid_boot_cycle(sram)) { printf("Invalid boot cycle partition!\n"); return CMD_RET_FAILURE; } printf("bootcycle counter: %d\n", sram->counter); if (sram->counter >= threshold) { printf("Reached maximum reboot.\n"); return CMD_RET_FAILURE; } return CMD_RET_SUCCESS; } U_BOOT_CMD( checkcycle, 2, 0, do_checkcycle, "checkcycle - check if maximum reboots reached.\n", "[max_reboots]" ); U_BOOT_CMD( inccycle, 2, 0, do_inccycle, "inccycle - increase boot cycle counter\n", NULL ); U_BOOT_CMD( resetcycle, 1, 0, do_resetcycle, "resetcycle - reset boot cycle counter to 0\n", NULL ); #endif /* CFG_CMD_BOOTCYCLE */