Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include "psp_verstage.h" |
| 4 | |
| 5 | #include <bl_uapp/bl_errorcodes_public.h> |
| 6 | #include <bl_uapp/bl_syscall_public.h> |
| 7 | #include <boot_device.h> |
| 8 | #include <commonlib/region.h> |
| 9 | #include <console/console.h> |
| 10 | #include <string.h> |
| 11 | |
| 12 | #define DEST_BUF_ALIGNMENT 16 |
| 13 | |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 14 | static uint32_t active_map_count; |
| 15 | |
| 16 | static void *boot_dev_mmap(const struct region_device *rd, size_t offset, size_t size) |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 17 | { |
| 18 | const struct mem_region_device *mdev; |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 19 | void *mapping = NULL; |
| 20 | uint32_t ret; |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 21 | |
| 22 | mdev = container_of(rd, __typeof__(*mdev), rdev); |
Karthikeyan Ramasubramanian | b6ab7ba | 2023-11-20 23:34:22 +0000 | [diff] [blame^] | 23 | if (CONFIG(PSP_VERSTAGE_MAP_ENTIRE_SPIROM)) |
| 24 | return &(mdev->base[offset]); |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 25 | |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 26 | if (mdev->base) { |
| 27 | if ((ret = svc_map_spi_rom(&mdev->base[offset], size, (void **)&mapping)) |
| 28 | != BL_OK) |
| 29 | printk(BIOS_ERR, "Failed(%d) to map SPI ROM offset: %zu, size: %zu\n", |
| 30 | ret, offset, size); |
| 31 | else |
| 32 | active_map_count++; |
| 33 | } |
| 34 | |
| 35 | return mapping; |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 36 | } |
| 37 | |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 38 | static int boot_dev_munmap(const struct region_device *rd, void *mapping) |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 39 | { |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 40 | uint32_t ret; |
| 41 | |
Karthikeyan Ramasubramanian | b6ab7ba | 2023-11-20 23:34:22 +0000 | [diff] [blame^] | 42 | if (CONFIG(PSP_VERSTAGE_MAP_ENTIRE_SPIROM)) |
| 43 | return 0; |
| 44 | |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 45 | active_map_count--; |
| 46 | if ((ret = svc_unmap_spi_rom(mapping)) != BL_OK) |
| 47 | printk(BIOS_ERR, "Failed(%d) to unmap SPI ROM mapping %p\n", ret, mapping); |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 48 | return 0; |
| 49 | } |
| 50 | |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 51 | static ssize_t boot_dev_mmap_readat(const struct region_device *rd, void *dest, |
| 52 | size_t offset, size_t size) |
| 53 | { |
| 54 | void *mapping = boot_dev_mmap(rd, offset, size); |
| 55 | |
| 56 | if (!mapping) |
| 57 | return -1; |
| 58 | |
| 59 | memcpy(dest, mapping, size); |
| 60 | boot_dev_munmap(rd, mapping); |
| 61 | return size; |
| 62 | } |
| 63 | |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 64 | static ssize_t boot_dev_dma_readat(const struct region_device *rd, void *dest, |
| 65 | size_t offset, size_t size) |
| 66 | { |
| 67 | size_t memcpy_size = ALIGN_UP((uintptr_t)dest, DEST_BUF_ALIGNMENT) - (uintptr_t)dest; |
| 68 | const struct mem_region_device *mdev = container_of(rd, __typeof__(*mdev), rdev); |
| 69 | int ret; |
| 70 | |
| 71 | if (memcpy_size > size) |
| 72 | memcpy_size = size; |
| 73 | /* Alignment requirement is only on dest buffer for CCP DMA. So do a memcpy |
| 74 | until the destination buffer alignment requirement is met. */ |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 75 | if (memcpy_size && boot_dev_mmap_readat(rd, dest, offset, memcpy_size) != memcpy_size) |
| 76 | return -1; |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 77 | |
| 78 | dest = ((char *)dest + memcpy_size); |
| 79 | offset += memcpy_size; |
| 80 | size -= memcpy_size; |
| 81 | if (!size) |
| 82 | return memcpy_size; |
| 83 | |
| 84 | ret = svc_ccp_dma((uint32_t)offset, dest, (uint32_t)size); |
| 85 | if (ret != BL_OK) { |
| 86 | printk(BIOS_ERR, "%s: Failed dest:%p offset:%zu size:%zu ret:%d\n", |
| 87 | __func__, dest, offset, size, ret); |
| 88 | return -1; |
| 89 | } |
| 90 | |
| 91 | return size + memcpy_size; |
| 92 | } |
| 93 | |
| 94 | static ssize_t boot_dev_readat(const struct region_device *rd, void *dest, |
| 95 | size_t offset, size_t size) |
| 96 | { |
| 97 | const struct mem_region_device *mdev = container_of(rd, __typeof__(*mdev), rdev); |
| 98 | |
| 99 | if (CONFIG(PSP_VERSTAGE_CCP_DMA)) |
| 100 | return boot_dev_dma_readat(rd, dest, offset, size); |
| 101 | |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 102 | return boot_dev_mmap_readat(rd, dest, offset, size); |
Karthikeyan Ramasubramanian | c2f6f35 | 2021-09-10 12:03:30 -0600 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | const struct region_device_ops boot_dev_rdev_ro_ops = { |
| 106 | .mmap = boot_dev_mmap, |
| 107 | .munmap = boot_dev_munmap, |
| 108 | .readat = boot_dev_readat, |
| 109 | }; |
| 110 | |
| 111 | static struct mem_region_device boot_dev = { |
| 112 | .rdev = REGION_DEV_INIT(&boot_dev_rdev_ro_ops, 0, CONFIG_ROM_SIZE), |
| 113 | }; |
| 114 | |
| 115 | const struct region_device *boot_device_ro(void) |
| 116 | { |
| 117 | if (!boot_dev.base) |
| 118 | boot_dev.base = (void *)map_spi_rom(); |
| 119 | return &boot_dev.rdev; |
| 120 | } |
Karthikeyan Ramasubramanian | 6f1b03b | 2023-04-21 14:26:51 -0600 | [diff] [blame] | 121 | |
| 122 | uint32_t boot_dev_get_active_map_count(void) |
| 123 | { |
| 124 | return active_map_count; |
| 125 | } |