1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2008-2011 Freescale Semiconductor, Inc.
4 */
5
6 /* #define DEBUG */
7
8 #include <asm/global_data.h>
9
10 #include <command.h>
11 #include <env.h>
12 #include <env_internal.h>
13 #include <fdtdec.h>
14 #include <linux/stddef.h>
15 #include <malloc.h>
16 #include <memalign.h>
17 #include <part.h>
18 #include <search.h>
19 #include <scsi.h>
20 #include <errno.h>
21 #include <dm/ofnode.h>
22
23 DECLARE_GLOBAL_DATA_PTR;
24 static env_t envbuf;
25
26 struct env_scsi_info {
27 struct blk_desc *blk;
28 struct disk_partition part;
29 int count;
30 };
31
32 static struct env_scsi_info env_part;
33
env_scsi_get_part(void)34 static inline struct env_scsi_info *env_scsi_get_part(void)
35 {
36 struct env_scsi_info *ep = &env_part;
37
38 if (scsi_get_blk_by_uuid(CONFIG_SCSI_ENV_PART_UUID, &ep->blk, &ep->part))
39 return NULL;
40
41 ep->count = CONFIG_ENV_SIZE / ep->part.blksz;
42
43 return ep;
44 }
45
env_scsi_save(void)46 static int env_scsi_save(void)
47 {
48 struct env_scsi_info *ep = env_scsi_get_part();
49 int ret;
50
51 if (!ep)
52 return -ENOENT;
53
54 ret = env_export(&envbuf);
55 if (ret)
56 return ret;
57
58 if (blk_dwrite(ep->blk, ep->part.start, ep->count, &envbuf) != ep->count)
59 return -EIO;
60
61 return 0;
62 }
63
env_scsi_erase(void)64 static int env_scsi_erase(void)
65 {
66 struct env_scsi_info *ep = env_scsi_get_part();
67
68 if (!ep)
69 return -ENOENT;
70
71 return (int)blk_derase(ep->blk, ep->part.start, ep->count);
72 }
73
74 #if defined(ENV_IS_EMBEDDED)
env_scsi_load(void)75 static int env_scsi_load(void)
76 {
77 return 0;
78 }
79 #else
env_scsi_load(void)80 static int env_scsi_load(void)
81 {
82 struct env_scsi_info *ep = env_scsi_get_part();
83 int ret;
84
85 if (!ep) {
86 env_set_default(CONFIG_SCSI_ENV_PART_UUID " partition not found", 0);
87 return -ENOENT;
88 }
89
90 if (blk_dread(ep->blk, ep->part.start, ep->count, &envbuf) != ep->count) {
91 env_set_default(CONFIG_SCSI_ENV_PART_UUID " partition read failed", 0);
92 return -EIO;
93 }
94
95 ret = env_import((char *)&envbuf, 1, H_EXTERNAL);
96 if (ret) {
97 debug("ENV import failed\n");
98 env_set_default("Cannot load environment", 0);
99 } else {
100 gd->env_addr = (ulong)envbuf.data;
101 }
102
103 return ret;
104 }
105 #endif
106
107 U_BOOT_ENV_LOCATION(scsi) = {
108 .location = ENVL_SCSI,
109 ENV_NAME("SCSI")
110 .load = env_scsi_load,
111 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_XPL_BUILD)
112 .save = env_save_ptr(env_scsi_save),
113 .erase = ENV_ERASE_PTR(env_scsi_erase),
114 #endif
115 };
116