3 Copyright 2005, Broadcom Corporation
6 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
7 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
8 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
9 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
17 #include <sys/ioctl.h>
18 #include <sys/mount.h>
23 #include <sys/reboot.h>
28 #define SHELL "/bin/sh"
42 static int fatalsigs
[] = {
53 static int initsigs
[] = {
62 static char *defenv
[] = {
65 "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
71 static int noconsole
= 0;
72 static volatile int state
= INIT
;
73 static volatile int signaled
= -1;
76 /* Set terminal settings to reasonable defaults */
77 static void set_term(int fd
)
83 /* set control chars */
84 tty
.c_cc
[VINTR
] = 3; /* C-c */
85 tty
.c_cc
[VQUIT
] = 28; /* C-\ */
86 tty
.c_cc
[VERASE
] = 127; /* C-? */
87 tty
.c_cc
[VKILL
] = 21; /* C-u */
88 tty
.c_cc
[VEOF
] = 4; /* C-d */
89 tty
.c_cc
[VSTART
] = 17; /* C-q */
90 tty
.c_cc
[VSTOP
] = 19; /* C-s */
91 tty
.c_cc
[VSUSP
] = 26; /* C-z */
93 /* use line dicipline 0 */
97 tty
.c_cflag
&= CBAUD
|CBAUDEX
|CSIZE
|CSTOPB
|PARENB
|PARODD
;
98 tty
.c_cflag
|= CREAD
|HUPCL
|CLOCAL
;
102 tty
.c_iflag
= ICRNL
| IXON
| IXOFF
;
105 tty
.c_oflag
= OPOST
| ONLCR
;
109 ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
| ECHOCTL
| ECHOKE
| IEXTEN
;
111 tcsetattr(fd
, TCSANOW
, &tty
);
114 static int console_init(void)
119 ioctl(0, TIOCNOTTY
, 0);
126 if ((fd
= open(_PATH_CONSOLE
, O_RDWR
)) < 0) {
127 /* Avoid debug messages is redirected to socket packet if no exist a UART chip, added by honor, 2003-12-04 */
128 open("/dev/null", O_RDONLY
);
129 open("/dev/null", O_WRONLY
);
130 open("/dev/null", O_WRONLY
);
131 perror(_PATH_CONSOLE
);
138 ioctl(0, TIOCSCTTY
, 1);
139 tcsetpgrp(0, getpgrp());
146 * Waits for a file descriptor to change status or unblocked signal
147 * @param fd file descriptor
148 * @param timeout seconds to wait before timing out or 0 for no timeout
149 * @return 1 if descriptor changed status or 0 if timed out or -1 on error
151 static int waitfor(int fd
, int timeout
)
154 struct timeval tv
= { timeout
, 0 };
158 return select(fd
+ 1, &rfds
, NULL
, NULL
, (timeout
> 0) ? &tv
: NULL
);
161 static pid_t
run_shell(int timeout
, int nowait
)
166 /* Wait for user input */
167 if (waitfor(STDIN_FILENO
, timeout
) <= 0) return 0;
169 switch (pid
= fork()) {
174 /* Reset signal handlers set for parent process */
175 for (sig
= 0; sig
< (_NSIG
-1); sig
++)
176 signal(sig
, SIG_DFL
);
180 printf("\n\nTomato %s\n\n", tomato_version
);
182 /* Now run it. The new program will take over this PID,
183 * so nothing further in init.c should be run. */
184 execve(SHELL
, (char *[]) { SHELL
, NULL
}, defenv
);
186 /* We're still here? Some error happened. */
194 waitpid(pid
, NULL
, 0);
200 static void shutdn(int rb
)
206 _dprintf("shutdn rb=%d\n", rb
);
209 for (i
= 0; i
< sizeof(fatalsigs
) / sizeof(fatalsigs
[0]); i
++)
210 sigaddset(&ss
, fatalsigs
[i
]);
211 for (i
= 0; i
< sizeof(initsigs
) / sizeof(initsigs
[0]); i
++)
212 sigaddset(&ss
, initsigs
[i
]);
213 sigaddset(&ss
, SIGCHLD
);
214 sigprocmask(SIG_BLOCK
, &ss
, NULL
);
216 for (i
= 30; i
> 0; --i
) {
217 if (((act
= check_action()) == ACT_IDLE
) || (act
== ACT_REBOOT
)) break;
218 cprintf("Busy with %d. Waiting before shutdown... %d\n", act
, i
);
221 set_action(ACT_REBOOT
);
233 umount("/jffs"); // may hang if not
239 for (i
= 4; i
> 0; --i
) {
250 reboot(rb
? RB_AUTOBOOT
: RB_HALT_SYSTEM
);
257 static void handle_fatalsigs(int sig
)
259 _dprintf("fatal sig=%d\n", sig
);
263 void handle_reap(int sig
)
265 while (waitpid(-1, NULL
, WNOHANG
) > 0) {
270 static void handle_initsigs(int sig
)
272 // TRACE_PT("sig=%d state=%d, signaled=%d\n", sig, state, signaled);
296 static int check_nv(const char *name
, const char *value
)
299 if (!nvram_match("manual_boot_nv", "1")) {
300 if (((p
= nvram_get(name
)) == NULL
) || (strcmp(p
, value
) != 0)) {
301 // cprintf("Error: Critical variable %s is invalid. Resetting.\n", name);
302 nvram_set(name
, value
);
309 static void check_bootnv(void)
314 if (get_model() != MODEL_WRT54G
) return;
315 if (strncmp(nvram_safe_get("pmon_ver"), "CFE", 3) != 0) return;
317 hardware
= check_hw_type();
318 if (!nvram_get("boardtype") ||
319 !nvram_get("boardnum") ||
320 !nvram_get("boardflags") ||
321 !nvram_get("clkfreq") ||
322 !nvram_get("os_flash_addr") ||
323 !nvram_get("dl_ram_addr") ||
324 !nvram_get("os_ram_addr") ||
325 !nvram_get("scratch") ||
326 !nvram_get("et0macaddr") ||
327 ((hardware
!= HW_BCM4704_BCM5325F
) && (!nvram_get("vlan0ports") || !nvram_get("vlan0hwname")))) {
328 cprintf("Unable to find critical settings, erasing NVRAM\n");
337 /* Lower the DDR ram drive strength , the value will be stable for all boards
338 Latency 3 is more stable for all ddr 20050420 by honor */
339 dirty
|= check_nv("sdram_init", "0x010b");
340 dirty
|= check_nv("sdram_config", "0x0062");
341 if (!nvram_match("debug_clkfix", "0")) {
342 dirty
|= check_nv("clkfreq", "216");
345 nvram_set("sdram_ncdl", "0x0");
347 dirty
|= check_nv("pa0itssit", "62");
348 dirty
|= check_nv("pa0b0", "0x15eb");
349 dirty
|= check_nv("pa0b1", "0xfa82");
350 dirty
|= check_nv("pa0b2", "0xfe66");
351 dirty
|= check_nv("pa0maxpwr", "0x4e");
353 case HW_BCM5352E
: // G v4, GS v3, v4
354 dirty
|= check_nv("sdram_init", "0x010b");
355 dirty
|= check_nv("sdram_config", "0x0062");
357 nvram_set("sdram_ncdl", "0x0");
359 dirty
|= check_nv("pa0itssit", "62");
360 dirty
|= check_nv("pa0b0", "0x168b");
361 dirty
|= check_nv("pa0b1", "0xfabf");
362 dirty
|= check_nv("pa0b2", "0xfeaf");
363 dirty
|= check_nv("pa0maxpwr", "0x4e");
364 dirty
|= check_nv("vlan0ports", "3 2 1 0 5*");
367 dirty
|= check_nv("pa0itssit", "62");
368 dirty
|= check_nv("pa0b0", "0x1326");
369 dirty
|= check_nv("pa0b1", "0xFB51");
370 dirty
|= check_nv("pa0b2", "0xFE87");
371 dirty
|= check_nv("pa0maxpwr", "0x4e");
373 case HW_BCM4704_BCM5325F
:
377 dirty
|= check_nv("pa0itssit", "62");
378 dirty
|= check_nv("pa0b0", "0x170c");
379 dirty
|= check_nv("pa0b1", "0xfa24");
380 dirty
|= check_nv("pa0b2", "0xfe70");
381 dirty
|= check_nv("pa0maxpwr", "0x48");
387 REBOOT
: // do a simple reboot
394 static int init_nvram(void)
396 unsigned long features
;
405 sprintf(s
, "%d", model
);
406 nvram_set("t_model", s
);
414 name
= "WRT54G/GS/GL";
415 switch (check_hw_type()) {
417 nvram_set("gpio2", "adm_eecs");
418 nvram_set("gpio3", "adm_eesk");
419 nvram_unset("gpio4");
420 nvram_set("gpio5", "adm_eedi");
421 nvram_set("gpio6", "adm_rc");
424 nvram_unset("gpio2");
425 nvram_unset("gpio3");
426 nvram_unset("gpio4");
427 nvram_unset("gpio5");
428 nvram_unset("gpio6");
431 nvram_set("opo", "0x0008");
432 nvram_set("ag0", "0x02");
435 nvram_set("gpio2", "ses_led");
436 nvram_set("gpio3", "ses_led2");
437 nvram_set("gpio4", "ses_button");
438 features
= SUP_SES
| SUP_WHAM_LED
;
445 if (!nvram_match("t_fix1", (char *)name
)) {
446 nvram_set ("vlan0hwname", "et0");
447 nvram_set ("vlan1hwname", "et0");
448 nvram_set("vlan0ports", "0 5*");
449 nvram_set("vlan1ports", "1 5");
450 nvram_set("vlan_enable", "1");
451 nvram_set("lan_ifnames", "vlan0 eth1");
452 nvram_set("gpio2", "ses_button");
453 nvram_set("reset_gpio", "7");
456 nvram_set("pa0itssit", "62");
457 nvram_set("pa0b0", "0x1542");
458 nvram_set("pa0b1", "0xfacb");
459 nvram_set("pa0b2", "0xfec7");
460 nvram_set("pa0maxpwr", "0x4c");
463 case MODEL_WRTSL54GS
:
466 features
= SUP_SES
| SUP_WHAM_LED
;
471 features
= SUP_SES
| SUP_AOSS_LED
| SUP_BRAU
;
474 case MODEL_WZRRSG54HP
:
477 features
= SUP_SES
| SUP_AOSS_LED
| SUP_HPAMP
;
479 case MODEL_WZRRSG54HP
:
480 name
= "WZR-RS-G54HP";
487 features
= SUP_SES
| SUP_AOSS_LED
| SUP_BRAU
| SUP_HPAMP
;
491 bf
= strtoul(nvram_safe_get("boardflags"), NULL
, 0);
497 if (nvram_match("wlx_hpamp", "")) {
498 if (nvram_get_int("wl_txpwr") > 10) nvram_set("wl_txpwr", "10");
499 nvram_set("wlx_hpamp", "1");
500 nvram_set("wlx_hperx", "0");
504 if (nvram_match("wlx_hpamp", "0")) {
510 if (nvram_match("wlx_hperx", "0")) {
517 sprintf(s
, "0x%lX", n
);
518 nvram_set("boardflags", s
);
522 syslog(LOG_WARNING
, "Unexpected: boardflag=%lX", bf
);
529 nvram_set("wl0gpio0", "130");
534 features
= SUP_SES
| SUP_AOSS_LED
;
536 case MODEL_WHR2A54G54
:
538 name
= "WHR2-A54G54";
539 features
= SUP_SES
| SUP_AOSS_LED
| SUP_BRAU
;
544 features
= SUP_SES
| SUP_AOSS_LED
;
549 features
= SUP_SES
| SUP_AOSS_LED
;
554 features
= SUP_SES
| SUP_AOSS_LED
;
564 features
= SUP_SES
| SUP_AOSS_LED
;
573 features
= SUP_NONVE
;
577 name
= "WR850G v2/v3";
578 features
= SUP_NONVE
;
584 if (!nvram_match("t_fix1", (char *)name
)) {
585 nvram_set("t_fix1", name
);
586 nvram_set("sdram_init", "0x0009"); // 32MB; defaults: 0x000b, 0x0009
587 nvram_set("vlan1ports", "0 5"); // default: 0 5u
588 nvram_set("lan_ifnames", "vlan0 eth1 eth2 eth3"); // set to "vlan0 eth2" by DD-WRT; default: vlan0 eth1
589 // !!TB - WLAN LED fix
590 nvram_set("wl0gpio0", "136");
597 if (!nvram_match("t_fix1", (char *)name
)) {
598 nvram_set("t_fix1", name
);
599 nvram_set("vlan1ports", "0 5"); // default: 0 5u
615 #ifndef WL_BSS_INFO_VERSION
616 #error WL_BSS_INFO_VERSION
618 #if WL_BSS_INFO_VERSION >= 108
624 nvram_set("opo", "12");
630 features
= SUP_SES
| SUP_AOSS_LED
| SUP_BRAU
;
632 nvram_set("opo", "0x0008");
633 nvram_set("ag0", "0x0C");
635 case MODEL_WL500GPv2
:
637 name
= "WL-500gP v2";
639 if (!nvram_match("t_fix1", (char *)name
)) {
640 if (nvram_match("vlan1ports", "4 5u")) {
641 nvram_set("vlan1ports", "4 5");
643 else if (nvram_match("vlan1ports", "0 5u")) { // 520GU?
644 nvram_set("vlan1ports", "0 5");
652 if (!nvram_match("t_fix1", (char *)name
)) {
653 nvram_set("t_fix1", name
);
654 nvram_set("vlan1ports", "0 5");
656 nvram_set("wl0gpio0", "0");
657 nvram_set("wl0gpio1", "136");
658 nvram_set("wl0gpio2", "0");
659 nvram_set("wl0gpio3", "0");
667 features
= SUP_SES
| SUP_AOSS_LED
| SUP_BRAU
| SUP_80211N
;
672 features
= SUP_SES
| SUP_80211N
;
678 sprintf(s
, "%s %s", mfr
, name
);
681 snprintf(s
, sizeof(s
), "%s %d/%s/%s/%s/%s", mfr
, check_hw_type(),
682 nvram_safe_get("boardtype"), nvram_safe_get("boardnum"), nvram_safe_get("boardrev"), nvram_safe_get("boardflags"));
685 nvram_set("t_model_name", s
);
687 sprintf(s
, "0x%lX", features
);
688 nvram_set("t_features", s
);
693 note: set wan_ifnameX if wan_ifname needs to be overriden
696 if (nvram_is_empty("wan_ifnameX")) {
698 nvram_set("wan_ifnameX", ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) ||
699 (check_hw_type() == HW_BCM4712
)) ? "vlan1" : "eth1");
701 p
= nvram_safe_get("wan_ifname");
702 if ((*p
== 0) || (nvram_match("wl_ifname", p
))) {
703 p
= ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) ||
704 (check_hw_type() == HW_BCM4712
)) ? "vlan1" : "eth1";
706 nvram_set("wan_ifnameX", p
);
711 nvram_set("wl_hwaddr", ""); // when disabling wireless, we must get null wireless mac ??
712 nvram_set("wl_country", "JP");
713 nvram_set("wl_country_code", "JP");
714 nvram_set("wan_get_dns", "");
715 nvram_set("wan_get_domain", "");
716 nvram_set("pppoe_pid0", "");
717 nvram_set("action_service", "");
718 nvram_set("jffs2_format", "0");
719 nvram_set("rrules_radio", "-1");
720 nvram_unset("https_crt_gen");
721 if (nvram_get_int("http_id_gen") == 1) nvram_unset("http_id");
723 nvram_unset("sch_rboot_last");
724 nvram_unset("sch_rcon_last");
725 nvram_unset("sch_c1_last");
726 nvram_unset("sch_c2_last");
727 nvram_unset("sch_c3_last");
729 nvram_set("brau_state", "");
730 if ((features
& SUP_BRAU
) == 0) nvram_set("script_brau", "");
731 if ((features
& SUP_SES
) == 0) nvram_set("sesx_script", "");
733 if (nvram_match("wl_net_mode", "disabled")) {
734 nvram_set("wl_radio", "0");
735 nvram_set("wl_net_mode", "mixed");
741 static void sysinit(void)
743 static const time_t tm
= 0;
752 mount("", "/proc", "proc", 0, NULL
);
753 mount("", "/tmp", "ramfs", 0, NULL
);
755 if (console_init()) noconsole
= 1;
759 static const char *mkd
[] = {
760 "/tmp/etc", "/tmp/var", "/tmp/home", "/tmp/mnt",
761 "/tmp/share", // !!TB
762 "/var/log", "/var/run", "/var/tmp", "/var/lib", "/var/lib/misc",
763 "/var/spool", "/var/spool/cron", "/var/spool/cron/crontabs", NULL
766 for (i
= 0; mkd
[i
]; ++i
) {
769 mkdir("/var/lock", 0777);
770 mkdir("/var/tmp/dhcp", 0777);
771 mkdir("/home/root", 0700);
773 f_write("/etc/hosts", NULL
, 0, 0, 0644); // blank
774 f_write("/etc/fstab", NULL
, 0, 0, 0644); // !!TB - blank
775 simple_unlock("cron");
776 simple_unlock("firewall");
777 simple_unlock("restrictions");
780 if ((d
= opendir("/rom/etc")) != NULL
) {
781 while ((de
= readdir(d
)) != NULL
) {
782 if (de
->d_name
[0] == '.') continue;
783 snprintf(s
, sizeof(s
), "%s/%s", "/rom/etc", de
->d_name
);
784 snprintf(t
, sizeof(t
), "%s/%s", "/etc", de
->d_name
);
789 symlink("/proc/mounts", "/etc/mtab");
791 #ifdef TCONFIG_SAMBASRV
792 if ((d
= opendir("/usr/codepages")) != NULL
) {
793 while ((de
= readdir(d
)) != NULL
) {
794 if (de
->d_name
[0] == '.') continue;
795 snprintf(s
, sizeof(s
), "/usr/codepages/%s", de
->d_name
);
796 snprintf(t
, sizeof(t
), "/usr/share/%s", de
->d_name
);
803 set_action(ACT_IDLE
);
805 for (i
= 0; defenv
[i
]; ++i
) {
810 printf("\n\nHit ENTER for console...\n\n");
816 for (i
= 0; i
< sizeof(fatalsigs
) / sizeof(fatalsigs
[0]); i
++) {
817 signal(fatalsigs
[i
], handle_fatalsigs
);
819 for (i
= 0; i
< sizeof(initsigs
) / sizeof(initsigs
[0]); i
++) {
820 signal(initsigs
[i
], handle_initsigs
);
822 signal(SIGCHLD
, handle_reap
);
824 switch (model
= get_model()) {
827 // need to cleanup some variables...
828 if ((nvram_get("t_model") == NULL
) && (nvram_get("MyFirmwareVersion") != NULL
)) {
829 nvram_unset("MyFirmwareVersion");
830 nvram_set("restore_defaults", "1");
835 system("nvram defaults --initcheck");
838 klogctl(8, NULL
, nvram_get_int("console_loglevel"));
842 hardware
= check_hw_type();
843 #if WL_BSS_INFO_VERSION >= 108
846 if ((hardware
== HW_BCM4702
) && (model
!= MODEL_WR850GV1
)) {
855 modprobe("tomato_ct");
857 set_host_domain_name();
869 int init_main(int argc
, char *argv
[])
878 #if defined(DEBUG_NOISY)
879 nvram_set("debug_logeval", "1");
880 nvram_set("debug_cprintf", "1");
881 nvram_set("debug_cprintf_file", "1");
882 nvram_set("debug_ddns", "1");
886 // TRACE_PT("main loop state=%d\n", state);
899 run_nvscript("script_shut", NULL
, 10);
906 // !!TB - USB Support
907 remove_storage_main();
910 if ((state
== REBOOT
) || (state
== HALT
)) {
911 shutdn(state
== REBOOT
);
919 // RESTART falls through
922 SET_LED(RELEASE_WAN_CONTROL
);
925 if (!nvram_get_int("usb_nolock")) {
926 fd
= file_lock("usb"); // hold off automount processing
930 run_nvscript("script_init", NULL
, 2);
932 if (nvram_get_int("usb_nolock"))
934 file_unlock(fd
); // allow to process usb hotplug events
937 * On RESTART some partitions can stay mounted if they are busy at the moment.
938 * In that case USB drivers won't unload, and hotplug won't kick off again to
939 * remount those drives that actually got unmounted. Make sure to remount ALL
940 * partitions here by simulating hotplug event.
942 if (state
== RESTART
) add_remove_usbhost("-1", 1);
950 syslog(LOG_INFO
, "Tomato %s", tomato_version
);
951 syslog(LOG_INFO
, "%s", nvram_safe_get("t_model_name"));
954 notice_set("sysup", "");
961 while (signaled
== -1) {
963 if ((!noconsole
) && ((!shell_pid
) || (kill(shell_pid
, 0) != 0))) {
964 shell_pid
= run_shell(0, 1);
977 int reboothalt_main(int argc
, char *argv
[])
979 int reboot
= (strstr(argv
[0], "reboot") != NULL
);
980 puts(reboot
? "Rebooting..." : "Shutting down...");
983 kill(1, reboot
? SIGTERM
: SIGQUIT
);