board: artik530_raptor: add update check feature for ota
authorJaewon Kim <jaewon02.kim@samsung.com>
Wed, 29 Mar 2017 01:22:34 +0000 (10:22 +0900)
committerJaewon Kim <jaewon02.kim@samsung.com>
Thu, 6 Apr 2017 10:12:12 +0000 (19:12 +0900)
This patch adds update check feature to support OTA(Over the Air).
This feature checks booting state information in FLAG partition.
If booting failed on updated partition,
partition changes to backuped boot partition.

Change-Id: Id6484f0d5307f15b36f9f23e03d424a3e8d3feb5
Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
board/s5p4418/artik530_raptor/Kconfig
board/s5p4418/artik530_raptor/Makefile
board/s5p4418/artik530_raptor/board.c
board/s5p4418/artik530_raptor/ota.c [new file with mode: 0644]
include/artik_ota.h [new file with mode: 0644]

index cd128c89a5cbb7793b993ded8b6de9fea128a038..ad2c2847dba5f8f7c377cfec8af8fd18b656152d 100644 (file)
@@ -3,5 +3,11 @@ if TARGET_ARTIK530_RAPTOR
 config SYS_BOARD
        default "artik530_raptor"
 
+config ARTIK_OTA
+       bool "ARTIK Update feature"
+       help
+         This feature provides OTA(Over-The-Air) function.
+         It updates kernel & modules partition without
+         the need of physical access.
 endif
 
index 95ab99dfc2e418d44db24aa0eef20bfcb7f0de21..cba948136180c8514d5aab2befda8d0768e69714 100644 (file)
@@ -5,4 +5,5 @@
 # SPDX-License-Identifier:      GPL-2.0+
 #
 
-obj-y  := board.o
+obj-y                  += board.o
+obj-$(CONFIG_ARTIK_OTA)        += ota.o
index 2aa1534fd396001e4fc9910475ef4d2959bec45d..033e68f0054a8d7e60afcffbaead7c7577138c88 100644 (file)
 #include <sensorid_artik.h>
 #endif
 
+#ifdef CONFIG_ARTIK_OTA
+#include <artik_ota.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef CONFIG_CHECK_BONDING_ID
@@ -295,6 +299,9 @@ int board_late_init(void)
 #endif
 #ifdef CONFIG_SENSORID_ARTIK
        get_sensorid(board_rev);
+#endif
+#ifdef CONFIG_ARTIK_OTA
+       check_ota_update();
 #endif
        return 0;
 }
diff --git a/board/s5p4418/artik530_raptor/ota.c b/board/s5p4418/artik530_raptor/ota.c
new file mode 100644 (file)
index 0000000..0669340
--- /dev/null
@@ -0,0 +1,120 @@
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <mapmem.h>
+#include <errno.h>
+#include <artik_ota.h>
+
+#ifndef CONFIG_FLAG_INFO_ADDR
+#define CONFIG_FLAG_INFO_ADDR  0x9A000000
+#endif
+
+static void write_flag_partition(void)
+{
+       char cmd[CMD_LEN] = {0, };
+
+       sprintf(cmd, "mmc write 0x%X 0x%X %X",
+                       CONFIG_FLAG_INFO_ADDR, FLAG_PART_BLOCK_START, 1);
+       run_command(cmd, 0);
+}
+
+static struct boot_info *read_flag_partition(void)
+{
+       char cmd[CMD_LEN] = {0, };
+
+       sprintf(cmd, "mmc read 0x%X 0x%X %X",
+                       CONFIG_FLAG_INFO_ADDR, FLAG_PART_BLOCK_START, 1);
+       run_command(cmd, 0);
+
+       return (struct boot_info *)map_sysmem(
+                       CONFIG_FLAG_INFO_ADDR, sizeof(struct boot_info));
+}
+
+int check_ota_update(void)
+{
+       struct boot_info *boot;
+       struct part_info *cur_part, *bak_part;
+       char cmd[CMD_LEN] = {0, };
+       char *bootcmd, *rootdev;
+
+       setenv("ota", "ota");
+       /* Do not check flag partition on recoveryboot mode */
+       bootcmd = getenv("bootcmd");
+       if (strstr(bootcmd, "recoveryboot") != NULL) {
+               return 0;
+       }
+
+       /* Check booted device */
+       rootdev = getenv("rootdev");
+       if (strncmp(rootdev, "0", 1) == 0) {
+               sprintf(cmd, "mmc dev %d", MMC_DEV_NUM);
+       } else if (strncmp(rootdev, "1", 1) == 0) {
+               sprintf(cmd, "mmc dev %d", SD_DEV_NUM);
+       } else {
+               printf("Cannot find rootdev\n");
+               return -1;
+       }
+       run_command(cmd, 0);
+
+       boot = read_flag_partition();
+       if (strncmp(boot->header_magic, HEADER_MAGIC, 32) != 0) {
+               printf("Cannot read FLAG information\n");
+               return -1;
+       }
+
+       if (boot->part_num == PART0) {
+               cur_part = &boot->part0;
+               bak_part = &boot->part1;
+       } else {
+               cur_part = &boot->part1;
+               bak_part = &boot->part0;
+       }
+
+       switch (boot->state) {
+       case BOOT_SUCCESS:
+               printf("Booting State = Normal(%d)\n", boot->part_num);
+               if (boot->part_num == PART0)
+                       setenv("bootpart", __stringify(CONFIG_BOOT_PART));
+               else
+                       setenv("bootpart", __stringify(CONFIG_BOOT1_PART));
+               setenv("rescue", "0");
+               break;
+       case BOOT_UPDATED:
+               if (cur_part->retry > 0) {
+                       printf("%s Partition Updated\n",
+                               boot->part_num == PART0 ? "PART0" : "PART1");
+                       cur_part->retry--;
+                       setenv("bootdelay", "0");
+                       setenv("rescue", "0");
+               /* Handling Booting Fail */
+               } else if (cur_part->retry == 0) {
+                       printf("Boot failed from %s\n",
+                               boot->part_num == PART0 ? "PART0" : "PART1");
+                       cur_part->state = BOOT_FAILED;
+                       if (bak_part->state == BOOT_SUCCESS) {
+                               if (boot->part_num == PART0)
+                                       boot->part_num = PART1;
+                               else
+                                       boot->part_num = PART0;
+                               boot->state = BOOT_SUCCESS;
+                               setenv("rescue", "1");
+                       } else {
+                               boot->state = BOOT_FAILED;
+                       }
+               }
+
+               if (boot->part_num == PART0)
+                       setenv("bootpart", __stringify(CONFIG_BOOT_PART));
+               else
+                       setenv("bootpart", __stringify(CONFIG_BOOT1_PART));
+               write_flag_partition();
+               break;
+       case BOOT_FAILED:
+       default:
+               printf("Booting State = Abnormal\n");
+               setenv("bootpart", __stringify(CONFIG_BOOT_PART));
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/include/artik_ota.h b/include/artik_ota.h
new file mode 100644 (file)
index 0000000..2cd8876
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics
+ * Author: Jaewon Kim <jaewon02.kim@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __ARTIK_OTA_H
+#define __ARTIK_OTA_H
+
+#define FLAG_PART_BLOCK_START  0x2000
+#define HEADER_MAGIC           "ARTIK_OTA"
+#define CMD_LEN                        128
+#define MMC_DEV_NUM            0
+#define SD_DEV_NUM             1
+
+enum boot_part {
+       PART0           = 0,
+       PART1,
+};
+
+enum boot_state {
+       BOOT_FAILED     = 0,
+       BOOT_SUCCESS,
+       BOOT_UPDATED,
+};
+
+struct part_info {
+       enum boot_state state;
+       char retry;
+       char tag[32];
+};
+
+struct boot_info {
+       char header_magic[32];
+       enum boot_part part_num;
+       enum boot_state state;
+       struct part_info part0;
+       struct part_info part1;
+};
+
+int check_ota_update(void);
+#endif