coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
sd_media.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <boot_device.h>
4 #include <symbols.h>
5 #include <console/console.h>
6 #include <assert.h>
8 #include <cbfs.h>
9 
10 #include <soc/ti/am335x/mmc.h>
11 #include <soc/ti/am335x/header.h>
12 
13 // Where the coreboot image is expected to be located on the SD card
14 // Only certain locations are allowed - check the AM335x technical reference
15 // manual for more details.
16 #define COREBOOT_IMAGE_OFFSET (128 * KiB)
17 
18 #define SD_BLOCK_SIZE 512
19 
20 static struct am335x_mmc_host sd_host;
21 static struct storage_media media;
22 
24 {
25  static uint8_t overflow_block[SD_BLOCK_SIZE];
26 
27  uint64_t blocks_read = storage_block_read(&media, block, 1, &overflow_block);
28 
29  if (blocks_read != 1) {
30  printk(BIOS_ERR, "Expected to read 1 block but read: %llu\n", blocks_read);
31  return 0;
32  }
33 
35 
36  int dest_index = 0;
37  for (int overflow_index = offset; overflow_index < (offset + count); overflow_index++)
38  dest[dest_index++] = overflow_block[overflow_index];
39 
40  return count;
41 }
42 
43 // This supports reads from a SD card that aren't necessarily aligned to the
44 // sd block size
45 static ssize_t sd_readat(const struct region_device *rdev, void *dest, size_t offset,
46  size_t count)
47 {
48  uint8_t *buffer = (uint8_t *)dest;
49 
50  uint64_t block_start = offset / SD_BLOCK_SIZE;
51  uint64_t block_end = (offset + count) / SD_BLOCK_SIZE;
52  uint64_t blocks = block_end - block_start + 1;
53 
54  // Read the last first, which might not be aligned on a SD block
55  uint32_t first_block_offset = offset % SD_BLOCK_SIZE;
56  size_t first_block_to_read = MIN(SD_BLOCK_SIZE - first_block_offset, count);
57  size_t bytes_read = partial_block_read(buffer, block_start, first_block_offset,
58  first_block_to_read);
59 
60  if (blocks == 1)
61  return bytes_read;
62 
63  buffer += bytes_read;
64 
65  if (blocks > 2) {
66  // Read all the "whole" blocks between the start and end blocks
67  uint64_t to_read = blocks - 2;
68  uint64_t blocks_read =
69  storage_block_read(&media, block_start + 1, to_read, (void *)buffer);
70 
71  if (blocks_read != to_read) {
72  printk(BIOS_ERR, "Expecting to read %llu blocks but only read %llu\n",
73  to_read, blocks_read);
74  return blocks_read * SD_BLOCK_SIZE;
75  }
76 
77  buffer += to_read * SD_BLOCK_SIZE;
78  bytes_read += to_read * SD_BLOCK_SIZE;
79  }
80 
81  // Read the last block, which might not be aligned on a SD block
82  bytes_read += partial_block_read(buffer, block_end, 0, count - bytes_read);
83 
84  return bytes_read;
85 }
86 
87 static const struct region_device_ops am335x_sd_ops = {
89  .munmap = mmap_helper_rdev_munmap,
90  .readat = sd_readat,
91 };
92 
93 extern struct omap_image_headers headers;
94 
96  &am335x_sd_ops, COREBOOT_IMAGE_OFFSET + sizeof(headers), CONFIG_ROM_SIZE,
97  &cbfs_cache);
98 
99 static bool init_done = false;
100 
102 {
103  if (init_done)
104  return;
105 
106  sd_host.sd_clock_hz = 96000000;
107  sd_host.reg = (void *)MMCHS0_BASE;
111 
112  init_done = true;
113 }
114 
115 const struct region_device *boot_device_ro(void)
116 {
117  return &sd_mdev.rdev;
118 }
#define assert(statement)
Definition: assert.h:74
#define MIN(a, b)
Definition: helpers.h:37
struct mem_pool cbfs_cache
Definition: cbfs.c:26
#define printk(level,...)
Definition: stdlib.h:16
static struct region_device rdev
Definition: flashconsole.c:14
static size_t offset
Definition: flashconsole.c:16
int storage_setup_media(struct storage_media *media, struct sd_mmc_ctrlr *ctrlr)
Definition: storage.c:188
void storage_display_setup(struct storage_media *media)
Definition: storage.c:88
uint64_t storage_block_read(struct storage_media *media, uint64_t start, uint64_t count, void *buffer)
Definition: storage.c:286
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
u8 buffer[C2P_BUFFER_MAXSIZE]
Definition: psp_smm.c:18
void * mmap_helper_rdev_mmap(const struct region_device *, size_t, size_t)
Definition: region.c:303
int mmap_helper_rdev_munmap(const struct region_device *, void *)
Definition: region.c:324
#define MMAP_HELPER_DEV_INIT(ops_, offset_, size_, mpool_)
Definition: region.h:219
static ssize_t sd_readat(const struct region_device *rdev, void *dest, size_t offset, size_t count)
Definition: sd_media.c:45
static size_t partial_block_read(uint8_t *dest, uint64_t block, uint32_t offset, uint32_t count)
Definition: sd_media.c:23
#define COREBOOT_IMAGE_OFFSET
Definition: sd_media.c:16
#define SD_BLOCK_SIZE
Definition: sd_media.c:18
const struct region_device * boot_device_ro(void)
Definition: sd_media.c:115
struct omap_image_headers headers
Definition: header.c:12
static const struct region_device_ops am335x_sd_ops
Definition: sd_media.c:87
static struct mmap_helper_region_device sd_mdev
Definition: sd_media.c:95
static struct storage_media media
Definition: sd_media.c:21
static bool init_done
Definition: sd_media.c:99
void boot_device_init(void)
Definition: sd_media.c:101
static struct am335x_mmc_host sd_host
Definition: sd_media.c:20
int am335x_mmc_init_storage(struct am335x_mmc_host *mmc_host)
Definition: mmc.c:258
#define MMCHS0_BASE
Definition: mmc.h:9
__SIZE_TYPE__ ssize_t
Definition: stddef.h:13
unsigned int uint32_t
Definition: stdint.h:14
unsigned long long uint64_t
Definition: stdint.h:17
unsigned char uint8_t
Definition: stdint.h:8
struct sd_mmc_ctrlr sd_mmc_ctrlr
Definition: mmc.h:43
struct am335x_mmc * reg
Definition: mmc.h:44
uint32_t sd_clock_hz
Definition: mmc.h:45
struct region_device rdev
Definition: region.h:216
void *(* mmap)(const struct region_device *, size_t, size_t)
Definition: region.h:68
#define count