diff --git a/sys/include/systm.h b/sys/include/systm.h index 5967000..94cbc76 100644 --- a/sys/include/systm.h +++ b/sys/include/systm.h @@ -70,6 +70,7 @@ extern dev_t pipedev; /* pipe device */ extern const char icode[]; /* user init code */ extern const char icodeend[]; /* its end */ +extern const char initflags[]; /* init flags string */ struct inode; daddr_t bmap (struct inode *ip, daddr_t bn, int rwflg, int flags); diff --git a/sys/kernel/init_main.c b/sys/kernel/init_main.c index 508813f..37e5045 100644 --- a/sys/kernel/init_main.c +++ b/sys/kernel/init_main.c @@ -196,6 +196,7 @@ main() * No return from sched. */ sched(); } + /* Child process with pid 1: init. */ s = splhigh(); p = u.u_procp; @@ -204,6 +205,15 @@ main() p->p_ssize = 1024; /* one kbyte of stack */ p->p_saddr = USER_DATA_END - 1024; bcopy ((caddr_t) icode, (caddr_t) USER_DATA_START, icodeend - icode); + + /* Start in single user more, if asked. */ + if (boothowto & RB_SINGLE) { + char *iflags = (char*) USER_DATA_START + (initflags - icode); + + /* Call /sbin/init with option '-s'. */ + iflags[1] = 's'; + } + /* * return goes to location 0 of user init code * just copied out. diff --git a/sys/pic32/fubarino/Config b/sys/pic32/fubarino/Config index d1f9690..6b8231e 100644 --- a/sys/pic32/fubarino/Config +++ b/sys/pic32/fubarino/Config @@ -26,6 +26,10 @@ options "BUS_DIV=1" # Bus clock divisor 1/2/4/8 # LED signal "LED_KERNEL" pin RE5 # kernel activity indicator +# Button +# Hold this button pressed at startup to enter single-user mode. +signal "BUTTON1" pin RE7 invert # PRG button, active low + # Root filesystem at /dev/sd0a, swap at /dev/sd0b config unix root on sd0a swap on sd0b diff --git a/sys/pic32/fubarino/Makefile b/sys/pic32/fubarino/Makefile index 1c87d5a..a35bd27 100644 --- a/sys/pic32/fubarino/Makefile +++ b/sys/pic32/fubarino/Makefile @@ -13,6 +13,7 @@ PARAM += -DGPIO5_ENABLED PARAM += -DGPIO6_ENABLED PARAM += -DADC_ENABLED PARAM += -DPWM_ENABLED +PARAM += -DBUTTON1_PORT=TRISE -DBUTTON1_PIN=7 -DBUTTON1_INVERT PARAM += -DLED_KERNEL_PORT=TRISE -DLED_KERNEL_PIN=5 PARAM += -DUSB_NUM_STRING_DESCRIPTORS=3 PARAM += -DUSB_MAX_EP_NUMBER=3 diff --git a/sys/pic32/machdep.c b/sys/pic32/machdep.c index 6cfa1c5..599885c 100644 --- a/sys/pic32/machdep.c +++ b/sys/pic32/machdep.c @@ -166,6 +166,26 @@ dev_t dumpdev = NODEV; dev_t pipedev; daddr_t dumplo = (daddr_t) 1024; +/* + * Check whether button 1 is pressed. + */ +static inline int +button1_pressed() +{ +#ifdef BUTTON1_PORT + int val; + + TRIS_SET(BUTTON1_PORT) = 1 << BUTTON1_PIN; + val = PORT_VAL(BUTTON1_PORT); +#ifdef BUTTON1_INVERT + val = ~val; +#endif + return (val >> BUTTON1_PIN) & 1; +#else + return 0; +#endif +} + /* * Machine dependent startup code */ @@ -391,6 +411,14 @@ startup() /* Get total RAM size. */ physmem = BMXDRMSZ; + + /* + * When button 1 is pressed - boot to single user mode. + */ + boothowto = 0; + if (button1_pressed()) { + boothowto |= RB_SINGLE; + } } static void cpuidentify() diff --git a/sys/pic32/startup.S b/sys/pic32/startup.S index fcbe9b2..9bb3b85 100644 --- a/sys/pic32/startup.S +++ b/sys/pic32/startup.S @@ -310,9 +310,11 @@ single_step_done: # Icode is copied out to process 1 to exec /sbin/init. # If the exec fails, process 1 exits. # - .globl icode, icodeend + .globl icode, icodeend, initflags .type icode, @function .type icodeend, @function + .type etcinit, @object + .type argv, @object icode: la $a0, UBASE move $a1, $a0 @@ -323,8 +325,9 @@ icode: syscall 1 # SYS_exit etcinit: .ascii "/sbin/init\0" + .align 2 initflags: - .ascii "-\0" # ASCII initflags + .ascii "-\0\0\0\0\0\0\0\0\0\0" # space for options argv: .word etcinit + 6 - icode + UBASE # address of "init\0" .word initflags - icode + UBASE # init options