820-wgt634u-nvram-fix.patch 7.3 KB

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