mmc: fsl_esdhc_spl: pre-PBL: check for BOOT signature instead of MBR/DBR
[platform/kernel/u-boot.git] / drivers / mmc / fsl_esdhc_spl.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2013 Freescale Semiconductor, Inc.
4  */
5
6 #include <common.h>
7 #include <cpu_func.h>
8 #include <hang.h>
9 #include <mmc.h>
10 #include <malloc.h>
11
12 /*
13  * The environment variables are written to just after the u-boot image
14  * on SDCard, so we must read the MBR to get the start address and code
15  * length of the u-boot image, then calculate the address of the env.
16  */
17 #define ESDHC_BOOT_SIGNATURE_OFF 0x40
18 #define ESDHC_BOOT_SIGNATURE    0x424f4f54
19 #define ESDHC_BOOT_IMAGE_SIZE   0x48
20 #define ESDHC_BOOT_IMAGE_ADDR   0x50
21 #define MBRDBR_BOOT_SIG_55      0x1fe
22 #define MBRDBR_BOOT_SIG_AA      0x1ff
23 #define CONFIG_CFG_DATA_SECTOR  0
24
25
26 void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
27 {
28         uint blk_start, blk_cnt, err;
29
30         struct mmc *mmc = find_mmc_device(0);
31         if (!mmc) {
32                 puts("spl: mmc device not found!!\n");
33                 hang();
34         }
35
36         if (mmc_init(mmc)) {
37                 puts("MMC init failed\n");
38                 return;
39         }
40
41         blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len;
42         blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
43
44         err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
45                                         vdst);
46         if (err != blk_cnt) {
47                 puts("spl: mmc read failed!!\n");
48                 hang();
49         }
50 }
51
52 /*
53  * The main entry for mmc booting. It's necessary that SDRAM is already
54  * configured and available since this code loads the main U-Boot image
55  * from mmc into SDRAM and starts it from there.
56  */
57
58 void __noreturn mmc_boot(void)
59 {
60         __attribute__((noreturn)) void (*uboot)(void);
61         uint blk_start, blk_cnt, err;
62 #ifndef CONFIG_FSL_CORENET
63         uchar *tmp_buf;
64         u32 blklen;
65         uchar val;
66 #ifndef CONFIG_SPL_FSL_PBL
67         u32 val32;
68 #endif
69         uint i, byte_num;
70 #endif
71         u32 offset, code_len;
72         struct mmc *mmc;
73
74         mmc = find_mmc_device(0);
75         if (!mmc) {
76                 puts("spl: mmc device not found!!\n");
77                 hang();
78         }
79
80 #ifdef CONFIG_FSL_CORENET
81         offset = CONFIG_SYS_MMC_U_BOOT_OFFS;
82         code_len = CONFIG_SYS_MMC_U_BOOT_SIZE;
83 #else
84         blklen = mmc->read_bl_len;
85         tmp_buf = malloc(blklen);
86         if (!tmp_buf) {
87                 puts("spl: malloc memory failed!!\n");
88                 hang();
89         }
90         memset(tmp_buf, 0, blklen);
91
92         /*
93         * Read source addr from sd card
94         */
95         err = mmc->block_dev.block_read(&mmc->block_dev,
96                                         CONFIG_CFG_DATA_SECTOR, 1, tmp_buf);
97         if (err != 1) {
98                 puts("spl: mmc read failed!!\n");
99                 hang();
100         }
101
102 #ifdef CONFIG_SPL_FSL_PBL
103         val = *(tmp_buf + MBRDBR_BOOT_SIG_55);
104         if (0x55 != val) {
105                 puts("spl: mmc MBR/DBR signature is not valid!!\n");
106                 hang();
107         }
108         val = *(tmp_buf + MBRDBR_BOOT_SIG_AA);
109         if (0xAA != val) {
110                 puts("spl: mmc MBR/DBR signature is not valid!!\n");
111                 hang();
112         }
113 #else
114         /*
115          * Booting from On-Chip ROM (eSDHC or eSPI), Document Number: AN3659, Rev. 2, 06/2012.
116          * Pre-PBL BootROMs (MPC8536E, MPC8569E, P2020, P1011, P1012, P1013, P1020, P1021, P1022)
117          * require custom BOOT signature on sector 0 and MBR/DBR signature is not required at all.
118          */
119         byte_num = 4;
120         val32 = 0;
121         for (i = 0; i < byte_num; i++) {
122                 val = *(tmp_buf + ESDHC_BOOT_SIGNATURE_OFF + i);
123                 val32 = (val32 << 8) + val;
124         }
125         if (val32 != ESDHC_BOOT_SIGNATURE) {
126                 puts("spl: mmc BOOT signature is not valid!!\n");
127                 hang();
128         }
129 #endif
130
131         byte_num = 4;
132         offset = 0;
133         for (i = 0; i < byte_num; i++) {
134                 val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i);
135                 offset = (offset << 8) + val;
136         }
137         offset += CONFIG_SYS_MMC_U_BOOT_OFFS;
138         /* Get the code size from offset 0x48 */
139         byte_num = 4;
140         code_len = 0;
141         for (i = 0; i < byte_num; i++) {
142                 val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i);
143                 code_len = (code_len << 8) + val;
144         }
145         code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS;
146         /*
147         * Load U-Boot image from mmc into RAM
148         */
149 #endif
150         blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
151         blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len;
152         err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
153                                         (uchar *)CONFIG_SYS_MMC_U_BOOT_DST);
154         if (err != blk_cnt) {
155                 puts("spl: mmc read failed!!\n");
156 #ifndef CONFIG_FSL_CORENET
157                 free(tmp_buf);
158 #endif
159                 hang();
160         }
161
162         /*
163         * Clean d-cache and invalidate i-cache, to
164         * make sure that no stale data is executed.
165         */
166         flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE);
167
168         /*
169         * Jump to U-Boot image
170         */
171         uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START;
172         (*uboot)();
173 }