blob: 1159e34468ad3eb08122eb8ff90b1909981d045b [file] [log] [blame]
David Brown5153bd62017-01-06 11:16:53 -07001/*
2 * Copyright (c) 2012-2014 Wind River Systems, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Marti Bolivareb940802017-05-01 23:15:29 -040017#include <assert.h>
David Brown5153bd62017-01-06 11:16:53 -070018#include <zephyr.h>
Andrzej Puzdrowski8e96b832017-09-08 16:49:14 +020019#include <gpio.h>
20#include <misc/__assert.h>
David Brown5153bd62017-01-06 11:16:53 -070021#include <flash.h>
22#include <asm_inline.h>
Ricardo Salveti8e4d44d2017-02-27 23:00:31 -030023#include <drivers/system_timer.h>
David Brown5153bd62017-01-06 11:16:53 -070024
Marti Bolivar51181cf2017-03-20 11:03:41 -040025#include "target.h"
26
Marti Bolivar4a97b4c2017-01-31 18:20:02 -050027#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
28#include "bootutil/bootutil_log.h"
Ricardo Salveti3a2c1242017-01-19 10:22:35 -020029#include "bootutil/image.h"
30#include "bootutil/bootutil.h"
Marti Bolivareb940802017-05-01 23:15:29 -040031#include "flash_map/flash_map.h"
Ricardo Salveti3a2c1242017-01-19 10:22:35 -020032
Andrzej Puzdrowski8e96b832017-09-08 16:49:14 +020033#ifdef CONFIG_MCUBOOT_SERIAL
34#include <boot_serial/boot_serial.h>
35#endif
36
David Brown5153bd62017-01-06 11:16:53 -070037struct device *boot_flash_device;
38
Andrew Boie7238f512017-03-02 13:39:06 -080039void os_heap_init(void);
40
Marti Bolivar97d997a2017-09-14 14:36:44 -040041extern void zephyr_flash_area_warn_on_open(void);
42
Andrew Boie7238f512017-03-02 13:39:06 -080043#if defined(CONFIG_ARM)
44struct arm_vector_table {
David Brown0d0652a2017-04-11 17:33:30 -060045 uint32_t msp;
46 uint32_t reset;
David Brown5153bd62017-01-06 11:16:53 -070047};
48
Andrew Boie7238f512017-03-02 13:39:06 -080049static void do_boot(struct boot_rsp *rsp)
50{
David Brown0d0652a2017-04-11 17:33:30 -060051 struct arm_vector_table *vt;
Marti Bolivareb940802017-05-01 23:15:29 -040052 uintptr_t flash_base;
53 int rc;
Andrew Boie7238f512017-03-02 13:39:06 -080054
David Brown0d0652a2017-04-11 17:33:30 -060055 /* The beginning of the image is the ARM vector table, containing
56 * the initial stack pointer address and the reset vector
57 * consecutively. Manually set the stack pointer and jump into the
58 * reset vector
59 */
Marti Bolivareb940802017-05-01 23:15:29 -040060 rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
61 assert(rc == 0);
62
63 vt = (struct arm_vector_table *)(flash_base +
64 rsp->br_image_off +
David Brown0d0652a2017-04-11 17:33:30 -060065 rsp->br_hdr->ih_hdr_size);
66 irq_lock();
67 sys_clock_disable();
68 _MspSet(vt->msp);
69 ((void (*)(void))vt->reset)();
Andrew Boie7238f512017-03-02 13:39:06 -080070}
71#else
72/* Default: Assume entry point is at the very beginning of the image. Simply
73 * lock interrupts and jump there. This is the right thing to do for X86 and
74 * possibly other platforms.
75 */
76static void do_boot(struct boot_rsp *rsp)
77{
Marti Bolivareb940802017-05-01 23:15:29 -040078 uintptr_t flash_base;
David Brown0d0652a2017-04-11 17:33:30 -060079 void *start;
Marti Bolivareb940802017-05-01 23:15:29 -040080 int rc;
Andrew Boie7238f512017-03-02 13:39:06 -080081
Marti Bolivareb940802017-05-01 23:15:29 -040082 rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
83 assert(rc == 0);
84
85 start = (void *)(flash_base + rsp->br_image_off +
86 rsp->br_hdr->ih_hdr_size);
Andrew Boie7238f512017-03-02 13:39:06 -080087
David Brown0d0652a2017-04-11 17:33:30 -060088 /* Lock interrupts and dive into the entry point */
89 irq_lock();
90 ((void (*)(void))start)();
Andrew Boie7238f512017-03-02 13:39:06 -080091}
92#endif
David Brown5153bd62017-01-06 11:16:53 -070093
94void main(void)
95{
David Brown0d0652a2017-04-11 17:33:30 -060096 struct boot_rsp rsp;
97 int rc;
David Brown5153bd62017-01-06 11:16:53 -070098
David Brown0d0652a2017-04-11 17:33:30 -060099 BOOT_LOG_INF("Starting bootloader");
Ricardo Salveti7cf3d9e2017-01-18 16:38:22 -0200100
David Brown0d0652a2017-04-11 17:33:30 -0600101 os_heap_init();
David Brown5153bd62017-01-06 11:16:53 -0700102
David Brown0d0652a2017-04-11 17:33:30 -0600103 boot_flash_device = device_get_binding(FLASH_DRIVER_NAME);
104 if (!boot_flash_device) {
105 BOOT_LOG_ERR("Flash device not found");
106 while (1)
107 ;
108 }
David Brown5153bd62017-01-06 11:16:53 -0700109
Andrzej Puzdrowski8e96b832017-09-08 16:49:14 +0200110#ifdef CONFIG_MCUBOOT_SERIAL
111
112 struct device *detect_port;
113 u32_t detect_value;
114
115 detect_port = device_get_binding(CONFIG_BOOT_SERIAL_DETECT_PORT);
116 __ASSERT(detect_port, "Error: Bad port for boot serial detection.\n");
117
118 rc = gpio_pin_configure(detect_port, CONFIG_BOOT_SERIAL_DETECT_PIN,
119 GPIO_DIR_IN | GPIO_PUD_PULL_UP);
120 __ASSERT(rc, "Error of boot detect pin initialization.\n");
121
122 rc = gpio_pin_read(detect_port, CONFIG_BOOT_SERIAL_DETECT_PIN,
123 &detect_value);
124 __ASSERT(rc, "Error of the reading the detect pin.\n");
125
126 if (detect_value == CONFIG_BOOT_SERIAL_DETECT_PIN_VAL) {
127 BOOT_LOG_INF("Enter the serial recovery mode");
128 boot_serial_start(CONFIG_BOOT_MAX_LINE_INPUT_LEN + 1);
129 __ASSERT(0, "Bootloader serial process was terminated unexpectedly.\n");
130 }
131#endif
132
David Brown0d0652a2017-04-11 17:33:30 -0600133 rc = boot_go(&rsp);
134 if (rc != 0) {
135 BOOT_LOG_ERR("Unable to find bootable image");
136 while (1)
137 ;
138 }
David Brown5153bd62017-01-06 11:16:53 -0700139
Marti Bolivar88f48d92017-05-01 22:30:02 -0400140 BOOT_LOG_INF("Bootloader chainload address offset: 0x%x",
141 rsp.br_image_off);
Marti Bolivar83a3cef2017-05-05 11:59:49 -0400142 zephyr_flash_area_warn_on_open();
David Brown0d0652a2017-04-11 17:33:30 -0600143 BOOT_LOG_INF("Jumping to the first image slot");
144 do_boot(&rsp);
David Brown5153bd62017-01-06 11:16:53 -0700145
David Brown0d0652a2017-04-11 17:33:30 -0600146 BOOT_LOG_ERR("Never should get here");
147 while (1)
148 ;
David Brown5153bd62017-01-06 11:16:53 -0700149}