820-wgt634u-nvram-fix.patch 7.3 KB

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