source: src/router/services/sysinit/sysinit-ipq806x.c @ 31712

Last change on this file since 31712 was 31712, checked in by brainslayer, 6 weeks ago

revert

File size: 15.8 KB
Line 
1/*
2 *
3 * Copyright (C) 2006 Sebastian Gottschall <gottschall@dd-wrt.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 *
19 * $Id:
20 */
21#include <stdio.h>
22#include <stdlib.h>
23#include <limits.h>
24#include <time.h>
25#include <unistd.h>
26#include <errno.h>
27#include <syslog.h>
28#include <signal.h>
29#include <string.h>
30#include <termios.h>
31#include <sys/klog.h>
32#include <sys/types.h>
33#include <sys/mount.h>
34#include <sys/reboot.h>
35#include <sys/stat.h>
36#include <sys/sysmacros.h>
37#include <sys/time.h>
38#include <sys/utsname.h>
39#include <sys/wait.h>
40#include <sys/ioctl.h>
41
42#include <bcmnvram.h>
43#include <shutils.h>
44#include <utils.h>
45#include <cymac.h>
46
47#include <arpa/inet.h>
48#include <sys/socket.h>
49#include <linux/if.h>
50#include <linux/sockios.h>
51#include <linux/mii.h>
52#include "devices/wireless.c"
53
54#define ALT_PART_NAME_LENGTH 16
55struct per_part_info {
56        char name[ALT_PART_NAME_LENGTH];
57        uint32_t primaryboot;
58        uint32_t upgraded;
59};
60
61#define NUM_ALT_PARTITION 3
62typedef struct {
63#define _SMEM_DUAL_BOOTINFO_MAGIC       0xA5A3A1A0
64        /* Magic number for identification when reading from flash */
65        uint32_t magic;
66        /* upgradeinprogress indicates to attempting the upgrade */
67        uint32_t upgradeinprogress;
68        /* numaltpart indicate number of alt partitions */
69        uint32_t numaltpart;
70
71        struct per_part_info per_part_entry[NUM_ALT_PARTITION];
72} ipq_smem_bootconfig_info_t;
73
74/* version 2 */
75#define SMEM_DUAL_BOOTINFO_MAGIC_START 0xA3A2A1A0
76#define SMEM_DUAL_BOOTINFO_MAGIC_END 0xB3B2B1B0
77
78typedef struct {
79        uint32_t magic_start;
80        uint32_t upgradeinprogress;
81        uint32_t age;
82        uint32_t numaltpart;
83        struct per_part_info per_part_entry[NUM_ALT_PARTITION];
84        uint32_t magic_end;
85} ipq_smem_bootconfig_v2_info_t;
86
87void start_finishupgrade(void)
88{
89        char mtdpath[64];
90        int mtd = getMTD("BOOTCONFIG");
91        sprintf(mtdpath, "/dev/mtdblock/%d", mtd);
92
93        ipq_smem_bootconfig_info_t *ipq_smem_bootconfig_info = NULL;
94        ipq_smem_bootconfig_v2_info_t *ipq_smem_bootconfig_v2_info = NULL;
95
96        unsigned int *smem = (unsigned int *)calloc(0x60000, 1);
97        FILE *fp = fopen(mtdpath, "rb");
98        if (fp) {
99                fread(smem, 0x60000, 1, fp);
100                fclose(fp);
101                int i;
102                unsigned int *p = smem;
103                for (i = 0; i < 0x60000 - sizeof(ipq_smem_bootconfig_v2_info); i += 4) {
104                        if (*p == SMEM_DUAL_BOOTINFO_MAGIC_START) {
105                                ipq_smem_bootconfig_v2_info = p;
106                                break;
107                        }
108                        if (*p == _SMEM_DUAL_BOOTINFO_MAGIC) {
109                                ipq_smem_bootconfig_info = p;
110                                break;
111                        }
112                        p++;
113                }
114
115        }
116        if (ipq_smem_bootconfig_v2_info) {
117                fprintf(stderr, "upgrade in progress: %d\n", ipq_smem_bootconfig_v2_info->upgradeinprogress);
118                int i;
119                if (ipq_smem_bootconfig_v2_info->upgradeinprogress) {
120                        for (i = 0; i < ipq_smem_bootconfig_v2_info->numaltpart; i++) {
121                                if (!strncmp(ipq_smem_bootconfig_v2_info->per_part_entry[i].name, "rootfs", 6)) {
122                                        ipq_smem_bootconfig_v2_info->per_part_entry[i].primaryboot = !ipq_smem_bootconfig_v2_info->per_part_entry[i].primaryboot;
123                                        ipq_smem_bootconfig_v2_info->per_part_entry[i].upgraded = 0;
124                                }
125                        }
126                }
127                ipq_smem_bootconfig_v2_info->upgradeinprogress = 0;
128        }
129        if (ipq_smem_bootconfig_info) {
130                fprintf(stderr, "upgrade in progress: %d\n", ipq_smem_bootconfig_info->upgradeinprogress);
131
132                int i;
133                if (ipq_smem_bootconfig_info->upgradeinprogress) {
134                        for (i = 0; i < ipq_smem_bootconfig_info->numaltpart; i++) {
135                                if (!strncmp(ipq_smem_bootconfig_info->per_part_entry[i].name, "rootfs", 6)) {
136                                        ipq_smem_bootconfig_info->per_part_entry[i].primaryboot = !ipq_smem_bootconfig_info->per_part_entry[i].primaryboot;
137                                        ipq_smem_bootconfig_info->per_part_entry[i].upgraded = 0;
138                                }
139                        }
140                }
141                ipq_smem_bootconfig_info->upgradeinprogress = 0;
142        }
143        fp = fopen(mtdpath, "wb");
144        if (fp) {
145                fwrite(smem, 0x60000, 1, fp);
146        }
147        fclose(fp);
148        free(smem);
149
150}
151
152void calcchecksum(void *caldata)        // works on little endian only so far. so consider to fix it when using on big endian systems
153{
154        int i;
155        unsigned short *cdata = (unsigned short *)caldata;
156        unsigned short *ptr_eeprom = (unsigned short *)caldata;
157        cdata[1] = 0;           // clear checksum for calculation
158        int size = cdata[0];
159        unsigned short crc = 0;
160        for (i = 0; i < size; i += 2) {
161                crc ^= *ptr_eeprom;
162                ptr_eeprom++;
163        }
164        crc = ~crc;
165        cdata[1] = crc;
166}
167
168static int getbootdevice(void)
169{
170        char mtdpath[64];
171        int mtd = getMTD("BOOTCONFIG");
172        sprintf(mtdpath, "/dev/mtdblock/%d", mtd);
173        ipq_smem_bootconfig_info_t *ipq_smem_bootconfig_info = NULL;
174        ipq_smem_bootconfig_v2_info_t *ipq_smem_bootconfig_v2_info = NULL;
175        int ret = -1;
176
177        unsigned int *smem = (unsigned int *)calloc(0x60000, 1);
178        FILE *fp = fopen(mtdpath, "rb");
179        if (fp) {
180                fread(smem, 0x60000, 1, fp);
181                fclose(fp);
182                int i;
183                unsigned int *p = smem;
184                for (i = 0; i < 0x60000 - sizeof(ipq_smem_bootconfig_v2_info); i += 4) {
185                        if (*p == SMEM_DUAL_BOOTINFO_MAGIC_START) {
186                                ipq_smem_bootconfig_v2_info = p;
187                                break;
188                        }
189                        if (*p == _SMEM_DUAL_BOOTINFO_MAGIC) {
190                                ipq_smem_bootconfig_info = p;
191                                break;
192                        }
193                        p++;
194                }
195
196        }
197        if (ipq_smem_bootconfig_v2_info) {
198                int i;
199                for (i = 0; i < ipq_smem_bootconfig_v2_info->numaltpart; i++) {
200                        if (!strncmp(ipq_smem_bootconfig_v2_info->per_part_entry[i].name, "rootfs", 6)) {
201                                if (ipq_smem_bootconfig_v2_info->per_part_entry[i].primaryboot)
202                                        ret = 1;
203                                else
204                                        ret = 0;
205                        }
206                }
207        }
208        if (ipq_smem_bootconfig_info) {
209                int i;
210                for (i = 0; i < ipq_smem_bootconfig_info->numaltpart; i++) {
211                        if (!strncmp(ipq_smem_bootconfig_info->per_part_entry[i].name, "rootfs", 6)) {
212                                if (ipq_smem_bootconfig_info->per_part_entry[i].primaryboot)
213                                        ret = 1;
214                                else
215                                        ret = 0;
216                        }
217                }
218        }
219        free(smem);
220        return ret;
221}
222
223static void setbootdevice(int dev)
224{
225        char mtdpath[64];
226        int mtd = getMTD("BOOTCONFIG");
227        sprintf(mtdpath, "/dev/mtdblock/%d", mtd);
228
229        ipq_smem_bootconfig_info_t *ipq_smem_bootconfig_info = NULL;
230        ipq_smem_bootconfig_v2_info_t *ipq_smem_bootconfig_v2_info = NULL;
231
232        unsigned int *smem = (unsigned int *)calloc(0x60000, 1);
233        FILE *fp = fopen(mtdpath, "rb");
234        if (fp) {
235                fread(smem, 0x60000, 1, fp);
236                fclose(fp);
237                int i;
238                unsigned int *p = smem;
239                for (i = 0; i < 0x60000 - sizeof(ipq_smem_bootconfig_v2_info); i += 4) {
240                        if (*p == SMEM_DUAL_BOOTINFO_MAGIC_START) {
241                                ipq_smem_bootconfig_v2_info = p;
242                                break;
243                        }
244                        if (*p == _SMEM_DUAL_BOOTINFO_MAGIC) {
245                                ipq_smem_bootconfig_info = p;
246                                break;
247                        }
248                        p++;
249                }
250
251        }
252        if (ipq_smem_bootconfig_v2_info) {
253                fprintf(stderr, "upgrade in progress: %d\n", ipq_smem_bootconfig_v2_info->upgradeinprogress);
254                int i;
255                for (i = 0; i < ipq_smem_bootconfig_v2_info->numaltpart; i++) {
256                        if (!strncmp(ipq_smem_bootconfig_v2_info->per_part_entry[i].name, "rootfs", 6)) {
257                                fprintf(stderr, "set bootdevice from %d to %d\n", ipq_smem_bootconfig_v2_info->per_part_entry[i].primaryboot, dev);
258                                ipq_smem_bootconfig_v2_info->per_part_entry[i].upgraded = 1;
259                        }
260                }
261                ipq_smem_bootconfig_v2_info->upgradeinprogress = 1;
262        }
263        if (ipq_smem_bootconfig_info) {
264                fprintf(stderr, "upgrade in progress: %d\n", ipq_smem_bootconfig_info->upgradeinprogress);
265
266                int i;
267                for (i = 0; i < ipq_smem_bootconfig_info->numaltpart; i++) {
268                        if (!strncmp(ipq_smem_bootconfig_info->per_part_entry[i].name, "rootfs", 6)) {
269                                fprintf(stderr, "set bootdevice from %d to %d\n", ipq_smem_bootconfig_info->per_part_entry[i].primaryboot, dev);
270                                ipq_smem_bootconfig_info->per_part_entry[i].upgraded = 1;
271                        }
272                }
273                ipq_smem_bootconfig_info->upgradeinprogress = 1;
274        }
275        fp = fopen(mtdpath, "wb");
276        if (fp) {
277                fwrite(smem, 0x60000, 1, fp);
278        }
279        fclose(fp);
280        free(smem);
281
282}
283
284void start_bootsecondary(void)
285{
286        setbootdevice(1);
287}
288
289void start_bootprimary(void)
290{
291        setbootdevice(0);
292}
293
294void *get_deviceinfo(char *var)
295{
296        static char res[256];
297        memset(res, 0, sizeof(res));
298        FILE *fp = fopen("/dev/mtdblock/12", "rb");
299        if (!fp)
300                return NULL;
301        char newname[64];
302        snprintf(newname, 64, "%s=", var);
303        char *mem = safe_malloc(0x2000);
304        fread(mem, 0x2000, 1, fp);
305        fclose(fp);
306        int s = (0x2000 - 1) - strlen(newname);
307        int i;
308        int l = strlen(newname);
309        for (i = 0; i < s; i++) {
310                if (!strncmp(mem + i, newname, l)) {
311                        strncpy(res, mem + i + l, 17);
312                        free(mem);
313                        return res;
314                }
315        }
316        free(mem);
317        return NULL;
318}
319
320void *get_deviceinfo_g10(char *var)
321{
322        static char res[256];
323        memset(res, 0, sizeof(res));
324        FILE *fp = fopen("/dev/mtdblock/9", "rb");
325        if (!fp)
326                return NULL;
327        char newname[64];
328        snprintf(newname, 64, "%s=", var);
329        char *mem = safe_malloc(0x2000);
330        fread(mem, 0x2000, 1, fp);
331        fclose(fp);
332        int s = (0x2000 - 1) - strlen(newname);
333        int i;
334        int l = strlen(newname);
335        for (i = 0; i < s; i++) {
336                if (!strncmp(mem + i, newname, l)) {
337                        strncpy(res, mem + i + l, 13);
338                        free(mem);
339                        return res;
340                }
341        }
342        free(mem);
343        return NULL;
344}
345
346static void setasrockcountry(void)
347{
348        char buf[32];
349        char c[32];
350        char *set = NULL;
351        char *set5 = NULL;
352        char rev = -1;
353        char rev5 = -1;
354#define defstr "HW.RegionDomain="
355        FILE *fp = popen("cat /dev/mtdblock9|grep HW.RegionDomain=", "r");
356        if (!fp)
357                return;
358        fread(buf, 1, 18, fp);
359        pclose(fp);
360        buf[strlen(defstr) + 2] = 0;
361        memset(c, 0, sizeof(c));
362        strncpy(c, &buf[strlen(defstr)], 2);
363//      fprintf(stderr,"isostr %s\n",buf);
364        fprintf(stderr, "iso %s\n", c);
365        char *ctry = getCountryByIso(c);
366        fprintf(stderr, "country %s\n", ctry);
367        if (!ctry)
368                return;
369        if (!nvram_get("nocountrysel"))
370                nvram_seti("nocountrysel", 1);
371        nvram_set("ath0_regdomain", ctry);
372        nvram_set("ath1_regdomain", ctry);
373}
374
375void start_sysinit(void)
376{
377        char buf[PATH_MAX];
378        struct stat tmp_stat;
379        time_t tm = 0;
380        FILE *fp = NULL;
381        if (!nvram_matchi("disable_watchdog", 1))
382                eval("watchdog");
383
384        /*
385         * Setup console
386         */
387
388        cprintf("sysinit() klogctl\n");
389        klogctl(8, NULL, nvram_geti("console_loglevel"));
390        cprintf("sysinit() get router\n");
391
392        char mtdpath[64];
393        int board = getRouterBrand();
394        // this is for TEW827 only. i dont know how it works for other boards. offsets might be different
395        int mtd = getMTD("art");
396        char *maddr = NULL;
397        sprintf(mtdpath, "/dev/mtdblock/%d", mtd);
398
399        if (board != ROUTER_NETGEAR_R7500)
400                fp = fopen(mtdpath, "rb");
401        if (fp != NULL) {
402                int newmac[6];
403                if (board == ROUTER_TRENDNET_TEW827)
404                        maddr = getUEnv("lan_mac");
405                if (board == ROUTER_LINKSYS_EA8500)
406                        maddr = get_deviceinfo("hw_mac_addr");
407
408                if (board == ROUTER_ASROCK_G10) {
409                        static char mg10[20];
410                        maddr = get_deviceinfo_g10("HW.LAN.MAC.Address");
411                        if (maddr) {
412                                sprintf(mg10, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", maddr[0] & 0xff, maddr[1] & 0xff, maddr[2] & 0xff, maddr[3] & 0xff, maddr[4] & 0xff, maddr[5] & 0xff, maddr[6] & 0xff, maddr[7] & 0xff,
413                                        maddr[8] & 0xff, maddr[9] & 0xff, maddr[10] & 0xff, maddr[11] & 0xff);
414                                maddr = &mg10[0];
415                        }
416                        setasrockcountry();
417                }
418
419                if (maddr) {
420                        fprintf(stderr, "sysinit using mac %s\n", maddr);
421                        sscanf(maddr, "%02x:%02x:%02x:%02x:%02x:%02x", &newmac[0], &newmac[1], &newmac[2], &newmac[3], &newmac[4], &newmac[5]);
422                }
423
424                fseek(fp, 0x1000, SEEK_SET);
425                char *smem = malloc(0x8000);
426                fread(smem, 0x8000, 1, fp);
427
428                fclose(fp);
429                if (maddr && (board == ROUTER_TRENDNET_TEW827 || board == ROUTER_LINKSYS_EA8500 || board == ROUTER_ASROCK_G10)) {       // board calibration data with real mac addresses
430                        int i;
431                        for (i = 0; i < 6; i++) {
432                                smem[i + 6] = newmac[i];
433                                smem[i + 6 + 0x4000] = newmac[i];
434                        }
435                }
436                calcchecksum(smem);
437                calcchecksum(&smem[0x4000]);
438
439                eval("rm", "-f", "/tmp/board1.bin");
440                fp = fopen("/tmp/board1.bin", "wb");
441                fwrite(smem, 12064, 1, fp);
442                fclose(fp);
443                fp = fopen("/tmp/board2.bin", "wb");
444                fwrite(&smem[0x4000], 12064, 1, fp);
445                fclose(fp);
446                free(smem);
447
448        }
449        /*
450         *
451         */
452        insmod("gsp");
453        insmod("slhc");
454
455        insmod("regmap-core");
456        insmod("regmap-i2c");
457        insmod("regmap-spi");
458        insmod("leds-tlc59116");
459        insmod("leds-gpio");
460
461        insmod("tmp421");
462        insmod("mii");
463        insmod("stmmac");       //for debugging purposes compiled as module
464        insmod("stmmac-platform");      //for debugging purposes compiled as module
465        insmod("qcom-wdt");
466
467        /*
468         * network drivers
469         */
470
471        //insmod("qdpc-host.ko");
472        eval("mount", "-t", "ubifs", "-o", "sync", "ubi0:rootfs_data", "/jffs");
473
474        switch (board) {
475        case ROUTER_TRENDNET_TEW827:
476                if (maddr) {
477                        eval("ifconfig", "eth0", "hw", "ether", getUEnv("wan_mac"));
478                        eval("ifconfig", "eth1", "hw", "ether", getUEnv("lan_mac"));
479                }
480                start_finishupgrade();
481                if (getbootdevice())
482                        nvram_seti("bootpartition", 1);
483                else
484                        nvram_seti("bootpartition", 0);
485                break;
486        case ROUTER_ASROCK_G10:
487                if (maddr) {
488                        eval("ifconfig", "eth1", "hw", "ether", maddr);
489                        eval("ifconfig", "eth0", "hw", "ether", maddr);
490                }
491                start_finishupgrade();
492                if (getbootdevice())
493                        nvram_seti("bootpartition", 1);
494                else
495                        nvram_seti("bootpartition", 0);
496                break;
497        case ROUTER_LINKSYS_EA8500:
498                if (maddr) {
499                        eval("ifconfig", "eth1", "hw", "ether", maddr);
500                        eval("ifconfig", "eth0", "hw", "ether", maddr);
501                        nvram_set("lan_hwaddr", maddr);
502                        nvram_commit();
503                }
504                eval("mtd", "resetbc", "s_env");
505                break;
506        default:
507                break;
508        }
509
510        switch (board) {
511        case ROUTER_NETGEAR_R7800:
512                system("swconfig dev switch0 set reset 1");
513                system("swconfig dev switch0 set enable_vlan 0");
514                system("swconfig dev switch0 vlan 1 set ports \"6 1 2 3 4\"");
515                system("swconfig dev switch0 vlan 2 set ports \"0 5\"");
516                system("swconfig dev switch0 set apply");
517                eval("ifconfig", "eth0", "up");
518                eval("ifconfig", "eth1", "up");
519//              eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD");
520//              eval("vconfig", "add", "eth1", "1");
521//              eval("vconfig", "add", "eth0", "2");
522                break;
523        case ROUTER_ASROCK_G10:
524                system("swconfig dev switch0 set reset 1");
525                system("swconfig dev switch0 set enable_vlan 1");
526                system("swconfig dev switch0 vlan 1 set ports \"2 3 4 5 6t\"");
527                system("swconfig dev switch0 vlan 2 set ports \"1 6t\"");
528                system("swconfig dev switch0 set apply");
529                eval("ifconfig", "eth1", "up");
530                eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD");
531                eval("vconfig", "add", "eth1", "1");
532                eval("vconfig", "add", "eth1", "2");
533                break;
534        case ROUTER_LINKSYS_EA8500:
535                system("swconfig dev switch0 set reset 1");
536                system("swconfig dev switch0 set enable_vlan 1");
537                system("swconfig dev switch0 vlan 1 set ports \"0t 1 2 3 4\"");
538                system("swconfig dev switch0 vlan 2 set ports \"0t 5\"");
539                system("swconfig dev switch0 set apply");
540                eval("ifconfig", "eth0", "up");
541                eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD");
542                eval("vconfig", "add", "eth0", "1");
543                eval("vconfig", "add", "eth0", "2");
544                break;
545        default:
546                system("swconfig dev switch0 set reset 1");
547                system("swconfig dev switch0 set enable_vlan 0");
548                system("swconfig dev switch0 vlan 1 set ports \"6 1 2 3 4\"");
549                system("swconfig dev switch0 vlan 2 set ports \"5 0\"");
550                system("swconfig dev switch0 set apply");
551                break;
552        }
553
554        eval("ifconfig", "eth1", "up");
555        eval("ifconfig", "eth0", "up");
556
557        detect_wireless_devices();
558
559        int s;
560        struct ifreq ifr;
561        if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))) {
562                char eabuf[32];
563
564                strncpy(ifr.ifr_name, "eth1", IFNAMSIZ);
565                ioctl(s, SIOCGIFHWADDR, &ifr);
566                char macaddr[32];
567
568                strcpy(macaddr, ether_etoa((char *)ifr.ifr_hwaddr.sa_data, eabuf));
569                nvram_set("et0macaddr", macaddr);
570                nvram_set("et0macaddr_safe", macaddr);
571                close(s);
572        }
573
574        switch (board) {
575        case ROUTER_LINKSYS_EA8500:
576                eval("ifconfig", "eth1", "down");
577                break;
578        default:
579                break;
580        }
581
582        /*
583         * Set a sane date
584         */
585        stime(&tm);
586        nvram_set("wl0_ifname", "ath0");
587        nvram_set("wl1_ifname", "ath1");
588}
589
590int check_cfe_nv(void)
591{
592        return 0;
593}
594
595int check_pmon_nv(void)
596{
597        return 0;
598}
599
600void start_overclocking(void)
601{
602}
603
604void enable_dtag_vlan(int enable)
605{
606
607}
Note: See TracBrowser for help on using the repository browser.