820-wgt634u-nvram-fix.patch 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. The Netgear wgt634u uses a different format for storing the
  2. configuration. This patch is needed to read out the correct
  3. configuration. The cfe_env.c file uses a different method way to read
  4. out the configuration than the in kernel cfe config reader.
  5. --- a/drivers/firmware/broadcom/Makefile
  6. +++ b/drivers/firmware/broadcom/Makefile
  7. @@ -1,4 +1,4 @@
  8. # SPDX-License-Identifier: GPL-2.0-only
  9. -obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o
  10. +obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o cfe_env.o
  11. obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx_sprom.o
  12. obj-$(CONFIG_TEE_BNXT_FW) += tee_bnxt_fw.o
  13. --- /dev/null
  14. +++ b/drivers/firmware/broadcom/cfe_env.c
  15. @@ -0,0 +1,228 @@
  16. +/*
  17. + * CFE environment variable access
  18. + *
  19. + * Copyright 2001-2003, Broadcom Corporation
  20. + * Copyright 2006, Felix Fietkau <[email protected]>
  21. + *
  22. + * This program is free software; you can redistribute it and/or modify it
  23. + * under the terms of the GNU General Public License as published by the
  24. + * Free Software Foundation; either version 2 of the License, or (at your
  25. + * option) any later version.
  26. + */
  27. +
  28. +#include <linux/init.h>
  29. +#include <linux/module.h>
  30. +#include <linux/kernel.h>
  31. +#include <linux/string.h>
  32. +#include <asm/io.h>
  33. +#include <linux/uaccess.h>
  34. +
  35. +#define NVRAM_SIZE (0x1ff0)
  36. +static char _nvdata[NVRAM_SIZE];
  37. +static char _valuestr[256];
  38. +
  39. +/*
  40. + * TLV types. These codes are used in the "type-length-value"
  41. + * encoding of the items stored in the NVRAM device (flash or EEPROM)
  42. + *
  43. + * The layout of the flash/nvram is as follows:
  44. + *
  45. + * <type> <length> <data ...> <type> <length> <data ...> <type_end>
  46. + *
  47. + * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
  48. + * The "length" field marks the length of the data section, not
  49. + * including the type and length fields.
  50. + *
  51. + * Environment variables are stored as follows:
  52. + *
  53. + * <type_env> <length> <flags> <name> = <value>
  54. + *
  55. + * If bit 0 (low bit) is set, the length is an 8-bit value.
  56. + * If bit 0 (low bit) is clear, the length is a 16-bit value
  57. + *
  58. + * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
  59. + * indicates the size of the length field.
  60. + *
  61. + * Flags are from the constants below:
  62. + *
  63. + */
  64. +#define ENV_LENGTH_16BITS 0x00 /* for low bit */
  65. +#define ENV_LENGTH_8BITS 0x01
  66. +
  67. +#define ENV_TYPE_USER 0x80
  68. +
  69. +#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
  70. +#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
  71. +
  72. +/*
  73. + * The actual TLV types we support
  74. + */
  75. +
  76. +#define ENV_TLV_TYPE_END 0x00
  77. +#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
  78. +
  79. +/*
  80. + * Environment variable flags
  81. + */
  82. +
  83. +#define ENV_FLG_NORMAL 0x00 /* normal read/write */
  84. +#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
  85. +#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
  86. +
  87. +#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
  88. +#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
  89. +
  90. +
  91. +/* *********************************************************************
  92. + * _nvram_read(buffer,offset,length)
  93. + *
  94. + * Read data from the NVRAM device
  95. + *
  96. + * Input parameters:
  97. + * buffer - destination buffer
  98. + * offset - offset of data to read
  99. + * length - number of bytes to read
  100. + *
  101. + * Return value:
  102. + * number of bytes read, or <0 if error occured
  103. + ********************************************************************* */
  104. +static int
  105. +_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
  106. +{
  107. + int i;
  108. + if (offset > NVRAM_SIZE)
  109. + return -1;
  110. +
  111. + for ( i = 0; i < length; i++) {
  112. + buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
  113. + }
  114. + return length;
  115. +}
  116. +
  117. +
  118. +static char*
  119. +_strnchr(const char *dest,int c,size_t cnt)
  120. +{
  121. + while (*dest && (cnt > 0)) {
  122. + if (*dest == c) return (char *) dest;
  123. + dest++;
  124. + cnt--;
  125. + }
  126. + return NULL;
  127. +}
  128. +
  129. +
  130. +
  131. +/*
  132. + * Core support API: Externally visible.
  133. + */
  134. +
  135. +/*
  136. + * Get the value of an NVRAM variable
  137. + * @param name name of variable to get
  138. + * @return value of variable or NULL if undefined
  139. + */
  140. +
  141. +char *cfe_env_get(unsigned char *nv_buf, const char *name)
  142. +{
  143. + int size;
  144. + unsigned char *buffer;
  145. + unsigned char *ptr;
  146. + unsigned char *envval;
  147. + unsigned int reclen;
  148. + unsigned int rectype;
  149. + int offset;
  150. + int flg;
  151. +
  152. + if (!strcmp(name, "nvram_type"))
  153. + return "cfe";
  154. +
  155. + size = NVRAM_SIZE;
  156. + buffer = &_nvdata[0];
  157. +
  158. + ptr = buffer;
  159. + offset = 0;
  160. +
  161. + /* Read the record type and length */
  162. + if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
  163. + goto error;
  164. + }
  165. +
  166. + while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
  167. +
  168. + /* Adjust pointer for TLV type */
  169. + rectype = *(ptr);
  170. + offset++;
  171. + size--;
  172. +
  173. + /*
  174. + * Read the length. It can be either 1 or 2 bytes
  175. + * depending on the code
  176. + */
  177. + if (rectype & ENV_LENGTH_8BITS) {
  178. + /* Read the record type and length - 8 bits */
  179. + if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
  180. + goto error;
  181. + }
  182. + reclen = *(ptr);
  183. + size--;
  184. + offset++;
  185. + }
  186. + else {
  187. + /* Read the record type and length - 16 bits, MSB first */
  188. + if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
  189. + goto error;
  190. + }
  191. + reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
  192. + size -= 2;
  193. + offset += 2;
  194. + }
  195. +
  196. + if (reclen > size)
  197. + break; /* should not happen, bad NVRAM */
  198. +
  199. + switch (rectype) {
  200. + case ENV_TLV_TYPE_ENV:
  201. + /* Read the TLV data */
  202. + if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
  203. + goto error;
  204. + flg = *ptr++;
  205. + envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
  206. + if (envval) {
  207. + *envval++ = '\0';
  208. + memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
  209. + _valuestr[(reclen-1)-(envval-ptr)] = '\0';
  210. +#if 0
  211. + printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
  212. +#endif
  213. + if(!strcmp(ptr, name)){
  214. + return _valuestr;
  215. + }
  216. + if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
  217. + return _valuestr;
  218. + }
  219. + break;
  220. +
  221. + default:
  222. + /* Unknown TLV type, skip it. */
  223. + break;
  224. + }
  225. +
  226. + /*
  227. + * Advance to next TLV
  228. + */
  229. +
  230. + size -= (int)reclen;
  231. + offset += reclen;
  232. +
  233. + /* Read the next record type */
  234. + ptr = buffer;
  235. + if (_nvram_read(nv_buf, ptr,offset,1) != 1)
  236. + goto error;
  237. + }
  238. +
  239. +error:
  240. + return NULL;
  241. +
  242. +}
  243. +
  244. --- a/drivers/firmware/broadcom/bcm47xx_nvram.c
  245. +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c
  246. @@ -33,6 +33,8 @@ struct nvram_header {
  247. static char nvram_buf[NVRAM_SPACE];
  248. static size_t nvram_len;
  249. static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000};
  250. +static int cfe_env;
  251. +extern char *cfe_env_get(char *nv_buf, const char *name);
  252. /**
  253. * bcm47xx_nvram_is_valid - check for a valid NVRAM at specified memory
  254. @@ -80,6 +82,26 @@ static int bcm47xx_nvram_find_and_copy(v
  255. return -EEXIST;
  256. }
  257. + cfe_env = 0;
  258. +
  259. + /* XXX: hack for supporting the CFE environment stuff on WGT634U */
  260. + if (res_size >= 8 * 1024 * 1024) {
  261. + u32 *src = (u32 *)(flash_start + 8 * 1024 * 1024 - 0x2000);
  262. + u32 *dst = (u32 *)nvram_buf;
  263. +
  264. + if ((*src & 0xff00ff) == 0x000001) {
  265. + printk("early_nvram_init: WGT634U NVRAM found.\n");
  266. +
  267. + for (i = 0; i < 0x1ff0; i++) {
  268. + if (*src == 0xFFFFFFFF)
  269. + break;
  270. + *dst++ = *src++;
  271. + }
  272. + cfe_env = 1;
  273. + return 0;
  274. + }
  275. + }
  276. +
  277. /* TODO: when nvram is on nand flash check for bad blocks first. */
  278. /* Try every possible flash size and check for NVRAM at its end */
  279. @@ -190,6 +212,13 @@ int bcm47xx_nvram_getenv(const char *nam
  280. if (!name)
  281. return -EINVAL;
  282. + if (cfe_env) {
  283. + value = cfe_env_get(nvram_buf, name);
  284. + if (!value)
  285. + return -ENOENT;
  286. + return snprintf(val, val_len, "%s", value);
  287. + }
  288. +
  289. if (!nvram_len) {
  290. err = nvram_init();
  291. if (err)