1 /* 2 * Copyright (c) 2022 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <malloc.h> 10 #include <version.h> 11 #include <asm/sections.h> 12 #include <asm/io.h> 13 #include <asm/u-boot.h> 14 #include <lzma/LzmaTools.h> 15 #include <asm/arch/rk_atags.h> 16 17 /********************** SPL framework weak ***********************/ 18 void board_init_f(ulong dummy) 19 { 20 /* Mainly to init secure */ 21 arch_cpu_init(); 22 } 23 24 ulong spl_relocate_stack_gd(void) 25 { 26 return 0; 27 } 28 29 int board_fit_config_name_match(const char *name) 30 { 31 return 0; 32 } 33 34 /********************** Decomp Header code ***********************/ 35 #define UART_FIFO_EMPTY (BIT(6) | BIT(5)) 36 #define UART_LSR 0x14 37 38 enum { 39 E_OK, 40 E_BD, 41 E_TLB, 42 E_MAGIC, 43 E_HCRC, 44 E_DCRC, 45 E_ALGO, 46 E_UNDEF, 47 }; 48 49 static const char *err_msg[] = { 50 "OK", "BD", "TLB", "MAGIC", "HCRC", "DCRC", "ALGO", "UNDEF" 51 }; 52 53 static ulong g_uart_base = CONFIG_DEBUG_UART_BASE; 54 55 static void put_char(char ch) 56 { 57 ulong base = g_uart_base; 58 59 if (!g_uart_base) 60 return; 61 62 writel(ch, base); 63 if (ch == '\n') 64 writel('\r', base); 65 66 while (!(__arch_getl(base + UART_LSR) & UART_FIFO_EMPTY)) 67 ; 68 } 69 70 static void put_string(const char *str) 71 { 72 while (*str) { 73 put_char(*str); 74 str++; 75 } 76 } 77 78 static void put_dec_0_19(int dec) 79 { 80 if (dec >= 10) { 81 put_char('1'); 82 dec -= 10; 83 } 84 85 put_char(dec + '0'); 86 } 87 88 static void put_hex(u32 hex) 89 { 90 uint8_t c, i = 8; 91 92 put_string("0x"); 93 while (i--) { 94 c = (hex & 0xf0000000) >> 28; 95 put_char(c < 0xa ? c + '0' : c - 0xa + 'a'); 96 hex <<= 4; 97 } 98 } 99 100 static void jump_entry(void *addr) 101 { 102 void (*os_entry)(void) = (void *)addr; 103 104 flush_dcache_all(); 105 106 /* 107 * Turn off I-cache and invalidate it 108 */ 109 icache_disable(); 110 invalidate_icache_all(); 111 112 /* 113 * Turn off D-cache 114 * dcache_disable() in turn flushes the d-cache and disables MMU 115 */ 116 dcache_disable(); 117 invalidate_dcache_all(); 118 119 dsb(); 120 isb(); 121 122 (*os_entry)(); 123 } 124 125 static struct tag *uart_init(void) 126 { 127 #if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \ 128 defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS) 129 struct tag *t; 130 131 t = atags_get_tag(ATAG_SERIAL); 132 if (t) { 133 if (t->u.serial.enable) 134 g_uart_base = t->u.serial.addr; 135 else 136 g_uart_base = 0; 137 } 138 #endif 139 return t; 140 } 141 142 static void print_ret(int err, int err_algo) 143 { 144 if (err) 145 put_string("ERR "); 146 147 put_string(err_msg[err]); 148 149 if (err_algo) { 150 put_char(' '); 151 put_dec_0_19(err_algo); 152 } 153 put_char('\n'); 154 } 155 156 #ifdef CONFIG_SPL_LZMA 157 static int un_lzma(const image_header_t *hdr, int *err_algo) 158 { 159 const void *data; 160 ulong load_addr; 161 SizeT lzma_len; 162 SizeT src_lenp; 163 int err; 164 165 load_addr = uimage_to_cpu(hdr->ih_load); 166 src_lenp = *(u32 *)(uimage_to_cpu(hdr->ih_size)); 167 data = (void *)hdr + sizeof(*hdr); 168 lzma_len = SZ_2M; /* default max size */ 169 err = lzmaBuffToBuffDecompress((uchar *)(load_addr), &lzma_len, 170 (uchar *)(data), src_lenp); 171 if (err) { 172 *err_algo = err; 173 err = E_ALGO; 174 } 175 176 return err; 177 } 178 #endif 179 180 static int decompress_image(const image_header_t *hdr, int *err_algo) 181 { 182 #ifdef CONFIG_SPL_LZMA 183 return un_lzma(hdr, err_algo); 184 #endif 185 return E_UNDEF; 186 } 187 188 void board_init_r(gd_t *dummy1, ulong dummy2) 189 { 190 const image_header_t *hdr; 191 struct tag *t; 192 ulong addr; 193 int err_algo = 0; 194 int err = 0; 195 196 t = uart_init(); 197 198 put_string("\nDECOMP " PLAIN_VERSION " (" U_BOOT_DATE " - " \ 199 U_BOOT_TIME ")\n\n"); 200 if (t) { 201 put_string("PreSerial: "); 202 put_char('0' + t->u.serial.id); 203 put_char('\n'); 204 } 205 put_string("Start... "); 206 207 /* init malloc */ 208 gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN); 209 gd->malloc_ptr = 0; 210 211 /* set up bank */ 212 #ifndef CONFIG_ARM64 213 if (!gd->bd) { 214 gd->bd = calloc(1, sizeof(bd_t)); 215 if (!gd->bd) { 216 err = E_BD; 217 goto out; 218 } 219 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; 220 gd->bd->bi_dram[0].size = SZ_64M; /* default */ 221 } 222 #endif 223 /* TLB memory should be SZ_16K base align and 4KB end align */ 224 gd->arch.tlb_size = PGTABLE_SIZE; 225 gd->arch.tlb_addr = (ulong)memalign(SZ_16K, ALIGN(PGTABLE_SIZE, SZ_4K)); 226 if (!gd->arch.tlb_addr) { 227 err = E_TLB; 228 goto out; 229 } 230 231 /* Enable dcache */ 232 dcache_enable(); 233 234 /* Check */ 235 hdr = (void *)(&__bss_end); 236 if (!image_check_magic(hdr)) { 237 err = E_MAGIC; 238 goto out; 239 } 240 241 if (!image_check_hcrc(hdr)) { 242 err = E_HCRC; 243 goto out; 244 } 245 246 if (!image_check_dcrc(hdr)) { 247 err = E_DCRC; 248 goto out; 249 } 250 251 /* Decompress... */ 252 err = decompress_image(hdr, &err_algo); 253 out: 254 print_ret(err, err_algo); 255 if (!err) { 256 addr = uimage_to_cpu(hdr->ih_load); 257 put_string("Jumping to "); 258 put_hex((u32)addr); 259 put_char('\n'); 260 261 /* jump! */ 262 jump_entry((void *)addr); 263 } 264 265 /* hang */ 266 put_string("\nPanic hang!"); 267 while (1) 268 ; 269 } 270 271