xref: /aosp_15_r20/external/coreboot/src/drivers/spi/boot_device_rw_nommap.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <boot_device.h>
4 #include <spi_flash.h>
5 #include <spi-generic.h>
6 #include <stdint.h>
7 
8 static struct spi_flash sfg;
9 static bool sfg_init_done;
10 
spi_readat(const struct region_device * rd,void * b,size_t offset,size_t size)11 static ssize_t spi_readat(const struct region_device *rd, void *b,
12 				size_t offset, size_t size)
13 {
14 	if (spi_flash_read(&sfg, offset, size, b))
15 		return -1;
16 
17 	return size;
18 }
19 
spi_writeat(const struct region_device * rd,const void * b,size_t offset,size_t size)20 static ssize_t spi_writeat(const struct region_device *rd, const void *b,
21 				size_t offset, size_t size)
22 {
23 	if (spi_flash_write(&sfg, offset, size, b))
24 		return -1;
25 
26 	return size;
27 }
28 
spi_eraseat(const struct region_device * rd,size_t offset,size_t size)29 static ssize_t spi_eraseat(const struct region_device *rd,
30 				size_t offset, size_t size)
31 {
32 	if (spi_flash_erase(&sfg, offset, size))
33 		return -1;
34 
35 	return size;
36 }
37 
38 static const struct region_device_ops spi_ops = {
39 	.readat = spi_readat,
40 	.writeat = spi_writeat,
41 	.eraseat = spi_eraseat,
42 };
43 
44 static const struct region_device spi_rw =
45 	REGION_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
46 
boot_device_rw_init(void)47 static void boot_device_rw_init(void)
48 {
49 	const int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS;
50 	const int cs = 0;
51 
52 	if (sfg_init_done == true)
53 		return;
54 
55 	/* Ensure any necessary setup is performed by the drivers. */
56 	spi_init();
57 
58 	if (!spi_flash_probe(bus, cs, &sfg))
59 		sfg_init_done = true;
60 }
61 
boot_device_rw(void)62 const struct region_device *boot_device_rw(void)
63 {
64 	/* Probe for the SPI flash device if not already done. */
65 	boot_device_rw_init();
66 
67 	if (sfg_init_done != true)
68 		return NULL;
69 
70 	return &spi_rw;
71 }
72 
boot_device_spi_flash(void)73 const struct spi_flash *boot_device_spi_flash(void)
74 {
75 	boot_device_rw_init();
76 
77 	if (sfg_init_done != true)
78 		return NULL;
79 
80 	return &sfg;
81 }
82 
boot_device_wp_region(const struct region_device * rd,const enum bootdev_prot_type type)83 int boot_device_wp_region(const struct region_device *rd,
84 			  const enum bootdev_prot_type type)
85 {
86 	uint32_t ctrlr_pr;
87 
88 	/* Ensure boot device has been initialized at least once. */
89 	boot_device_init();
90 
91 	const struct spi_flash *boot_dev = boot_device_spi_flash();
92 
93 	if (boot_dev == NULL)
94 		return -1;
95 
96 	if (type == MEDIA_WP) {
97 		if (spi_flash_is_write_protected(boot_dev,
98 						 region_device_region(rd)) != 1) {
99 			enum spi_flash_status_reg_lockdown lock =
100 				SPI_WRITE_PROTECTION_REBOOT;
101 			if (CONFIG(BOOTMEDIA_SPI_LOCK_REBOOT))
102 				lock = SPI_WRITE_PROTECTION_REBOOT;
103 			else if (CONFIG(BOOTMEDIA_SPI_LOCK_PIN))
104 				lock = SPI_WRITE_PROTECTION_PIN;
105 			else if (CONFIG(BOOTMEDIA_SPI_LOCK_PERMANENT))
106 				lock = SPI_WRITE_PROTECTION_PERMANENT;
107 
108 			return spi_flash_set_write_protected(boot_dev,
109 						region_device_region(rd), lock);
110 		}
111 
112 		/* Already write protected */
113 		return 0;
114 	}
115 
116 	switch (type) {
117 	case CTRLR_WP:
118 		ctrlr_pr = WRITE_PROTECT;
119 		break;
120 	case CTRLR_RP:
121 		ctrlr_pr = READ_PROTECT;
122 		break;
123 	case CTRLR_RWP:
124 		ctrlr_pr = READ_WRITE_PROTECT;
125 		break;
126 	default:
127 		return -1;
128 	}
129 
130 	return spi_flash_ctrlr_protect_region(boot_dev,
131 					region_device_region(rd), ctrlr_pr);
132 }
133