1.. SPDX-License-Identifier: GPL-2.0+
2.. sectionauthor:: Simon Glass <sjg@chromium.org>
3
4Chromebook Coral
5================
6
7Coral is a Chromebook (or really about 20 different Chromebooks) which use the
8Intel Apollo Lake platform (APL). The 'reef' Chromebooks use the same APL SoC so
9should also work. Some later ones based on Glacier Lake (GLK) need various
10changes in GPIOs, etc. but are very similar.
11
12It is hoped that this port can enable ports to embedded APL boards which are
13starting to appear.
14
15Note that booting U-Boot on APL is already supported by coreboot and
16Slim Bootloader. This documentation refers to a 'bare metal' port.
17
18
19Building
20--------
21
22First, you need the following binary blobs:
23
24   * descriptor.bin - Intel flash descriptor
25   * fitimage.bin - Base flash image structure
26   * fsp_m.bin - FSP-M, for setting up SDRAM
27   * fsp_s.bin - FSP-S, for setting up Silicon
28   * vbt.bin - for setting up display
29
30These binaries do not seem to be available publicly. If you have a ROM image,
31such as santa.bin then you can do this::
32
33  cbfstool santa.bin extract -n fspm.bin -f fsp-m.bin
34  cbfstool santa.bin extract -n fsps.bin -f fsp-s.bin
35  cbfstool santa.bin extract -n vbt-santa.bin -f vbt.bin
36  mkdir tmp
37  cd tmp
38  dump_fmap -x ../santa.bin
39  mv SI_DESC ../descriptor.bin
40  mv IFWI ../fitimage.bin
41
42Put all of these files in `board/google/chromebook_coral` so they can be found
43by the build.
44
45To build::
46
47  make O=/tmp/b/chromebook_coral chromebook_coral_defconfig
48  make O=/tmp/b/chromebook_coral -s -j30 all
49
50That should produce `/tmp/b/chrombook_coral/u-boot.rom` which you can use with
51a Dediprog em100::
52
53  em100 -s -c w25q128fw -d /tmp/b/chromebook_coral/u-boot.rom -r
54
55or you can use flashrom to write it to the board. If you do that, make sure you
56have a way to restore the old ROM without booting the board. Otherwise you may
57brick it. Having said that, you may find these instructions useful if you want
58to unbrick your device:
59
60  https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md
61
62You can buy Suzy-Q from Sparkfun:
63
64  https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/docs/ccd.md#suzyq-suzyqable
65
66Note that it will hang at the SPL prompt for 21 seconds. When booting into
67Chrome OS it will always select developer mode, so will wipe anything you have
68on the device if you let it proceed. You have two seconds in U-Boot to stop the
69auto-boot prompt and several seconds at the 'developer wipe' screen to stop it
70wiping the disk.
71
72Here is the console output::
73
74  U-Boot TPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
75  Trying to boot from Mapped SPI
76
77  U-Boot SPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
78  Trying to boot from Mapped SPI
79
80
81  U-Boot 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
82
83  CPU:   Intel(R) Celeron(R) CPU N3450 @ 1.10GHz
84  DRAM:  3.9 GiB
85  MMC:   sdmmc@1b,0: 1, emmc@1c,0: 2
86  Video: 1024x768x32 @ b0000000
87  Model: Google Coral
88  Net:   No ethernet found.
89  SF: Detected w25q128fw with page size 256 Bytes, erase size 4 KiB, total 16 MiB
90  Hit any key to stop autoboot:  0
91  cmdline=console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=${uuid}/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=${uuid} add_efi_memmap boot=local noresume noswap i915.modeset=1 Kernel command line: "console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off  "
92  Setup located at 00090000:
93
94  ACPI RSDP addr      : 7991f000
95  E820: 14 entries
96                Addr              Size  Type
97      d0000000     1000000  <NULL>
98             0       a0000  RAM
99         a0000       60000  Reserved
100      7b000000      800000  Reserved
101      7b800000     4800000  Reserved
102      7ac00000      400000  Reserved
103        100000     ff00000  RAM
104      10000000     2151000  Reserved
105      12151000    68aaf000  RAM
106     100000000    80000000  RAM
107      e0000000    10000000  Reserved
108      7991bfd0     12e4030  Reserved
109      d0000000    10000000  Reserved
110      fed10000        8000  Reserved
111  Setup sectors       : 1e
112  Root flags          : 1
113  Sys size            : 63420
114  RAM size            : 0
115  Video mode          : ffff
116  Root dev            : 0
117  Boot flag           : 0
118  Jump                : 66eb
119  Header              : 53726448
120                        Kernel V2
121  Version             : 20d
122  Real mode switch    : 0
123  Start sys           : 1000
124  Kernel version      : 38cc
125     @00003acc:
126  Type of loader      : 80
127                        U-Boot, version 0
128  Load flags          : 81
129                      : loaded-high can-use-heap
130  Setup move size     : 8000
131  Code32 start        : 100000
132  Ramdisk image       : 0
133  Ramdisk size        : 0
134  Bootsect kludge     : 0
135  Heap end ptr        : 8e00
136  Ext loader ver      : 0
137  Ext loader type     : 0
138  Command line ptr    : 99000
139     console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off
140  Initrd addr max     : 7fffffff
141  Kernel alignment    : 200000
142  Relocatable kernel  : 1
143  Min alignment       : 15
144                      : 200000
145  Xload flags         : 3
146                      : 64-bit-entry can-load-above-4gb
147  Cmdline size        : 7ff
148  Hardware subarch    : 0
149  HW subarch data     : 0
150  Payload offset      : 26e
151  Payload length      : 612045
152  Setup data          : 0
153  Pref address        : 1000000
154  Init size           : 1383000
155  Handover offset     : 0
156
157  Starting kernel ...
158
159  Timer summary in microseconds (17 records):
160         Mark    Elapsed  Stage
161            0          0  reset
162      155,279    155,279  TPL
163      237,088     81,809  end phase
164      237,533        445  SPL
165      816,456    578,923  end phase
166      817,357        901  board_init_f
167    1,061,751    244,394  board_init_r
168    1,402,435    340,684  id=64
169    1,430,071     27,636  main_loop
170    5,532,057  4,101,986  start_kernel
171
172  Accumulated time:
173                     685  dm_r
174                   2,817  fast_spi
175                  33,095  dm_spl
176                  52,468  dm_f
177                 208,242  fsp-m
178                 242,221  fsp-s
179                 332,710  mmap_spi
180
181
182Boot flow - TPL
183---------------
184
185Apollo Lake boots via an IFWI (Integrated Firmware Image). TPL is placed in
186this, in the IBBL entry.
187
188On boot, an on-chip microcontroller called the CSE (Converged Security Engine)
189sets up some SDRAM at ffff8000 and loads the TPL image to that address. The
190SRAM extends up to the top of 32-bit address space, but the last 2KB is the
191start16 region, so the TPL image must be 30KB at most, and CONFIG_TPL_TEXT_BASE
192must be ffff8000. Actually the start16 region is small and it could probably
193move from f800 to fe00, providing another 1.5KB, but TPL is only about 19KB so
194there is no need to change it at present. The size limit is enforced by
195CONFIG_TPL_SIZE_LIMIT to avoid producing images that won't boot.
196
197TPL (running from start.S) first sets up CAR (Cache-as-RAM) which provides
198larger area of RAM for use while booting. CAR is mapped at CONFIG_SYS_CAR_ADDR
199(fef00000) and is 768KB in size. It then sets up the stack in the botttom 64KB
200of this space (i.e. below fef10000). This means that the stack and early
201malloc() region in TPL can be 64KB at most.
202
203TPL operates without CONFIG_TPL_PCI enabled so PCI config access must use the
204x86-specific functions pci_x86_write_config(), etc. SPL creates a simple-bus
205device so that PCI devices are bound by driver model. Then arch_cpu_init_tpl()
206is called to early init on various devices. This includes placing PCI devices
207at hard-coded addresses in the memory map. PCI auto-config is not used.
208
209Most of the 16KB ROM is mapped into the very top of memory, except for the
210Intel descriptor (first 4KB) and the space for SRAM as above.
211
212TPL does not set up a bloblist since at present it does not have anything to
213pass to SPL.
214
215Once TPL is done it loads SPL from ROM using either the memory-mapped SPI or by
216using the Intel fast SPI driver. SPL is loaded into CAR, at the address given
217by CONFIG_SPL_TEXT_BASE, which is normally fef10000.
218
219Note that booting using the SPI driver results in an TPL image that is about
22026KB in size instead of 19KB. Also boot speed is worse by about 340ms. If you
221really want to use the driver, enable CONFIG_APL_SPI_FLASH_BOOT and set
222BOOT_FROM_FAST_SPI_FLASH to true[2].
223
224
225Boot flow - SPL
226---------------
227
228SPL (running from start_from_tpl.S) continues to use the same stack as TPL.
229It calls arch_cpu_init_spl() to set up a few devices, then init_dram() loads
230the FSP-M binary into CAR and runs to, to set up SDRAM. The address of the
231output 'HOB' list (Hand-off-block) is stored into gd->arch.hob_list for parsing.
232There is a 2GB chunk of SDRAM starting at 0 and the rest is at 4GB.
233
234PCI auto-config is not used in SPL either, but CONFIG_SPL_PCI is defined, so
235proper PCI access is available and normal dm_pci_read_config() calls can be
236used. However PCI auto-config is not used so the same static memory mapping set
237up by TPL is still active.
238
239SPL on x86 always runs with CONFIG_SPL_SEPARATE_BSS=y and BSS is at 120000
240(see u-boot-spl.lds). This works because SPL doesn't access BSS until after
241board_init_r(), as per the rules, and DRAM is available then.
242
243SPL sets up a bloblist and passes the SPL hand-off information to U-Boot proper.
244This includes a pointer to the HOB list as well as DRAM information. See
245struct arch_spl_handoff. The bloblist address is set by CONFIG_BLOBLIST_ADDR,
246normally 100000.
247
248SPL uses SPI flash to update the MRC caches in ROM. This speeds up subsequent
249boots. Be warned that SPL can take 30 seconds without this cache! This is a
250known issue with Intel SoCs with modern DRAM and apparently cannot be improved.
251The MRC caches are used to work around this.
252
253Once SPL is finished it loads U-Boot into SDRAM at CONFIG_SYS_TEXT_BASE, which
254is normally 1110000. Note that CAR is still active.
255
256
257Boot flow - U-Boot pre-relocation
258---------------------------------
259
260U-Boot (running from start_from_spl.S) starts running in RAM and uses the same
261stack as SPL. It does various init activities before relocation. Notably
262arch_cpu_init_dm() sets up the pin muxing for the chip using a very large table
263in the device tree.
264
265PCI auto-config is not used before relocation, but CONFIG_PCI of course is
266defined, so proper PCI access is available. The same static memory mapping set
267up by TPL is still active until relocation.
268
269As per usual, U-Boot allocates memory at the top of available RAM (a bit below
2702GB in this case) and copies things there ready to relocate itself. Notably
271reserve_arch() does not reserve space for the HOB list returned by FSP-M since
272this is already located in RAM.
273
274U-Boot then shuts down CAR and jumps to its relocated version.
275
276
277Boot flow - U-Boot post-relocation
278----------------------------------
279
280U-Boot starts up normally, running near the top of RAM. After driver model is
281running, arch_fsp_init_r() is called which loads and runs the FSP-S binary.
282This updates the HOB list to include graphics information, used by the fsp_video
283driver.
284
285PCI autoconfig is done and a few devices are probed to complete init. Most
286others are started only when they are used.
287
288Note that FSP-S is supposed to run after CAR has been shut down, which happens
289immediately before U-Boot starts up in its relocated position. Therefore we
290cannot run FSP-S before relocation. On the other hand we must run it before
291PCI auto-config is done, since FSP-S may show or hide devices. The first device
292that probes PCI after relocation is the serial port, in initr_serial(), so FSP-S
293must run before that. A corollary is that loading FSP-S must be done without
294using the SPI driver, to avoid probing PCI and causing an autoconfig, so
295memory-mapped reading is always used for FSP-S.
296
297It would be possible to tear down CAR in SPL instead of U-Boot. The SPL handoff
298information could make sure it does not include any pointers into CAR (in fact
299it doesn't). But tearing down CAR in U-Boot allows the initial state used by TPL
300and SPL to be read by U-Boot, which seems useful. It also matches how older
301platforms start up (those that don't use SPL).
302
303
304Performance
305-----------
306
307Bootstage is used through all phases of U-Boot to keep accurate timimgs for
308boot. Use 'bootstage report' in U-Boot to see the report, e.g.::
309
310    Timer summary in microseconds (16 records):
311           Mark    Elapsed  Stage
312              0          0  reset
313        155,325    155,325  TPL
314        204,014     48,689  end TPL
315        204,385        371  SPL
316        738,633    534,248  end SPL
317        739,161        528  board_init_f
318        842,764    103,603  board_init_r
319      1,166,233    323,469  main_loop
320      1,166,283         50  id=175
321
322    Accumulated time:
323                        62  fast_spi
324                       202  dm_r
325                     7,779  dm_spl
326                    15,555  dm_f
327                   208,357  fsp-m
328                   239,847  fsp-s
329                   292,143  mmap_spi
330
331CPU performance is about 3500 DMIPS::
332
333    => dhry
334    1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS
335
336
337Partial memory map
338------------------
339
340::
341
342    ffffffff       Top of ROM (and last byte of 32-bit address space)
343    ffff8000       TPL loaded here (from IFWI)
344    ff000000       Bottom of ROM
345    fefc0000       Top of CAR region
346    fef96000       Stack for FSP-M
347    fef40000 59000 FSP-M (also VPL loads here)
348    fef11000       SPL loaded here
349    fef10000       CONFIG_BLOBLIST_ADDR
350    fef10000       Stack top in TPL, SPL and U-Boot before relocation
351    fef00000  1000 CONFIG_BOOTSTAGE_STASH_ADDR
352    fef00000       Base of CAR region
353
354       30000       AP_DEFAULT_BASE (used to start up additional CPUs)
355       f0000       CONFIG_ROM_TABLE_ADDR
356      120000       BSS (defined in u-boot-spl.lds)
357      200000       FSP-S (which is run after U-Boot is relocated)
358     1110000       CONFIG_SYS_TEXT_BASE
359
360
361Speeding up SPL for development
362-------------------------------
363
364The 21-second wait for memory training is annoying during development, since
365every new image incurs this cost when booting. There is no cache to fall back on
366since that area of the image is empty on start-up.
367
368You can add suitable cache contents to the image to fix this, for development
369purposes only, like this::
370
371   # Read the image back after booting through SPL
372   em100 -s -c w25q128fw -u image.bin
373
374   # Extract the two cache regions
375   binman extract -i image.bin extra *cache
376
377   # Move them into the source directory
378   mv *cache board/google/chromebook_coral
379
380Then add something like this to the devicetree::
381
382  #if IS_ENABLED(CONFIG_HAVE_MRC) || IS_ENABLED(CONFIG_FSP_VERSION2)
383     /* Provide initial contents of the MRC data for faster development */
384     rw-mrc-cache {
385        type = "blob";
386        /* Mirror the offset in spi-flash@0 */
387        offset = <0xff8e0000>;
388        size = <0x10000>;
389        filename = "board/google/chromebook_coral/rw-mrc-cache";
390     };
391     rw-var-mrc-cache {
392        type = "blob";
393        size = <0x1000>;
394        filename = "board/google/chromebook_coral/rw-var-mrc-cache";
395     };
396  #endif
397
398This tells binman to put the cache contents in the same place as the
399`rw-mrc-cache` and `rw-var-mrc-cache` regions defined by the SPI-flash driver.
400
401
402Supported peripherals
403---------------------
404
405The following have U-Boot drivers:
406
407   - UART
408   - SPI flash
409   - Video
410   - MMC (dev 0) and micro-SD (dev 1)
411   - Chrome OS EC
412   - Cr50 (security chip)
413   - Keyboard
414   - USB
415
416
417To do
418-----
419
420- Finish peripherals
421   - Sound (Intel I2S support exists, but need da7219 driver)
422- Use FSP-T binary instead of our own CAR implementation
423- Use the official FSP package instead of the coreboot one
424- Suspend / resume
425- Fix MMC which seems to try to read even though the card is empty
426- Fix USB3 crash "WARN halted endpoint, queueing URB anyway."
427
428
429Credits
430-------
431
432This is a spare-time project conducted slowly over a long period of time.
433
434Much of the code for this port came from Coreboot, an open-source firmware
435project similar to U-Boot's SPL in terms of features.
436
437Also see [2] for information about the boot flow used by coreboot. It is
438similar, but has an extra postcar stage. U-Boot doesn't need this since it
439supports relocating itself in memory.
440
441
442[2] Intel PDF https://www.coreboot.org/images/2/23/Apollolake_SoC.pdf
443