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