forked from AspeedTech-BMC/rom-patcher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootloader.c
119 lines (102 loc) · 2.79 KB
/
bootloader.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdint.h>
#include <stdio.h>
#include "config.h"
#include "bitops.h"
#include "ast2600.h"
#include "opcode.h"
/**
* double-word (4-byte) aligned size
*/
#define DW_ALIGNED_DW_SIZE(byte_size) (((byte_size) + 0x3) >> 2)
/**
* double-word (4-byte) aligned size in byte
*/
#define DW_ALIGNED_BYTE_SIZE(byte_size) (DW_ALIGNED_DW_SIZE(byte_size) << 2)
struct cm3_image_header {
uint32_t magic;
uint32_t src; /* byte address */
uint32_t dst;
uint32_t size_dw; /* size is in uint32_t */
};
// SPI Flash layout
// 2000_0000 - 2000_001F: reserved for ARM Cortex A7
// 2000_0020 - 2000_003F: secure boot header
// 2000_0040 ~ : ROM patch
uint32_t get_cm3_bin_size(char *cm3_bin_name)
{
FILE *fb;
uint32_t size = 0;
fb = fopen(cm3_bin_name, "rb");
if (!fb) {
printf("can not open cm3 bin file: %s\n", cm3_bin_name);
return 0;
}
fseek(fb, 0, SEEK_END);
size = ftell(fb);
fclose(fb);
return size;
}
void attach_cm3_binary(FILE *fp, char *cm3_bin_name)
{
struct cm3_image_header hdr;
FILE *fb;
fpos_t fp_cur;
uint8_t data;
fgetpos(fp, &fp_cur);
hdr.magic = 0x55667788;
hdr.src = vPOS(fp_cur) + sizeof(hdr);
hdr.dst = CONFIG_CM3_DEST_ADDR;
hdr.size_dw = DW_ALIGNED_DW_SIZE(get_cm3_bin_size(cm3_bin_name));
fwrite(&hdr, 1, sizeof(hdr), fp);
fb = fopen(cm3_bin_name, "rb");
if (!fb) {
printf("can not open cm3 bin file: %s\n", cm3_bin_name);
return;
}
fseek(fb, 0, SEEK_SET);
while (fread(&data, 1, sizeof(data), fb)) {
fwrite(&data, 1, sizeof(data), fp);
}
fclose(fb);
/* make pointer be 4-byte aligned */
fgetpos(fp, &fp_cur);
vPOS(fp_cur) = DW_ALIGNED_BYTE_SIZE(vPOS(fp_cur));
fsetpos(fp, &fp_cur);
}
void copy_cm3(FILE *fp, fpos_t start)
{
fpos_t fp_cur;
struct cm3_image_header hdr;
/*
1. backup current pointer
2. set pointer to image start for reading the image header
3. restore current pointer
*/
fgetpos(fp, &fp_cur);
fsetpos(fp, &start);
fread(&hdr, 1, sizeof(hdr), fp);
fsetpos(fp, &fp_cur);
/* copy CM3 bootcode */
jeq_code(fp, SBC_BASE + OTP_QSR, BIT(26), BIT(26), "l_copy_from_sram");
jeq_code(fp, SBC_BASE + SBC_STS, BIT(5), BIT(5), "l_copy_from_sram");
cp_code(fp, SPI_BASE + hdr.src, hdr.dst, hdr.size_dw);
jmp_code(fp, "l_copy_done");
declare_label(fp, "l_copy_from_sram");
cp_code(fp, SRAM_BASE + hdr.src, hdr.dst, hdr.size_dw);
declare_label(fp, "l_copy_done");
}
void enable_cm3(FILE *fp)
{
wr_single(fp, SCU_BASE + 0xa00, 0);
wr_single(fp, SCU_BASE + 0xa04, CONFIG_CM3_DEST_ADDR);
wr_single(fp, SCU_BASE + 0xa48, 3);
wr_single(fp, SCU_BASE + 0xa48, 1);
wr_single(fp, SCU_BASE + 0xa08, CONFIG_CM3_DEST_ADDR + 0x01000000);
wr_single(fp, SCU_BASE + 0xa0c, CONFIG_CM3_DEST_ADDR + 0x02000000);
wr_single(fp, SCU_BASE + 0xa00, 2);
delay_code(fp, 500);
wr_single(fp, SCU_BASE + 0xa00, 0);
#if 0
wr_single(fp, SCU_BASE + 0xa00, 1);
#endif
}