static int command_mem_dump(int argc, char **argv) { volatile uint32_t *address; uint32_t value, num = 1, i; char *e; if (argc < 2) return EC_ERROR_PARAM_COUNT; address = (uint32_t *)(uintptr_t)strtoi(argv[1], &e, 0); if (*e) return EC_ERROR_PARAM1; if (argc >= 3) num = strtoi(argv[2], &e, 0); for (i = 0; i < num; i++) { value = address[i]; if (0 == (i%4)) ccprintf("\n%08X: %08x", address+i, value); else ccprintf(" %08x", value); cflush(); /* Lots of output could take a while. * Let other things happen, too */ if (!(i % 0x100)) { watchdog_reload(); usleep(10 * MSEC); } } ccprintf("\n"); cflush(); return EC_SUCCESS; }
void cts_task(void) { enum cts_rc rc; int i; gpio_enable_interrupt(GPIO_CTS_IRQ1); gpio_enable_interrupt(GPIO_CTS_IRQ2); interrupt_enable(); for (i = 0; i < CTS_TEST_ID_COUNT; i++) { clear_state(); sync(); rc = tests[i].run(); interrupt_enable(); CPRINTF("\n%s %d\n", tests[i].name, rc); cflush(); } CPRINTS("Interrupt test suite finished"); cflush(); while (1) { watchdog_reload(); sleep(1); } }
static int command_crash(int argc, char **argv) { if (argc < 2) return EC_ERROR_PARAM1; if (!strcasecmp(argv[1], "assert")) { ASSERT(0); } else if (!strcasecmp(argv[1], "divzero")) { int zero = 0; cflush(); if (argc >= 3 && !strcasecmp(argv[2], "unsigned")) ccprintf("%08x", (unsigned long)1 / zero); else ccprintf("%08x", (long)1 / zero); #ifdef CONFIG_CMD_STACKOVERFLOW } else if (!strcasecmp(argv[1], "stack")) { stack_overflow_recurse(1); #endif } else if (!strcasecmp(argv[1], "unaligned")) { cflush(); ccprintf("%08x", *(volatile int *)0xcdef); } else if (!strcasecmp(argv[1], "watchdog")) { while (1) ; } else { return EC_ERROR_PARAM1; } /* Everything crashes, so shouldn't get back here */ return EC_ERROR_UNKNOWN; }
/* * This is for NOT having enough hibernate (more precisely, the stand-by mode) * wake-up source pin. STM32L100 supports 3 wake-up source pins: * * WKUP1 (PA0) -- used for ACOK_PMU * WKUP2 (PC13) -- used for LID_OPEN * WKUP3 (PE6) -- cannot be used due to IC package. * * However, we need the power button as a wake-up source as well and there is * no available pin for us (we don't want to move the ACOK_PMU pin). * * Fortunately, the STM32L is low-power enough so that we don't need the * super-low-power mode. So, we fake this hibernate mode and accept the * following wake-up source. * * RTC alarm (faked as well). * Power button * Lid open * AC detected * * The original issue is here: crosbug.com/p/25435. */ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) { int i; fake_hibernate = 1; #ifdef CONFIG_POWER_COMMON /* * A quick hack to stop annoying messages from charger task. * * When the battery is under 3%, the power task would call * power_off() to shutdown AP. However, the power_off() would * notify the HOOK_CHIPSET_SHUTDOWN, where the last hook is * charge_shutdown() and it hibernates the power task (infinite * loop -- not real CPU hibernate mode). Unfortunately, the * charger task is still running. It keeps generating annoying * log message. * * Thus, the hack is to set the power state machine (before we * enter infinite loop) so that the charger task thinks the AP * is off and stops generating messages. */ power_set_state(POWER_G3); #endif /* * Change keyboard outputs to high-Z to reduce power draw. * We don't need corresponding code to change them back, * because fake hibernate is always exited with a reboot. * * A little hacky to do this here. */ for (i = GPIO_KB_OUT00; i < GPIO_KB_OUT00 + KEYBOARD_COLS; i++) gpio_set_flags(i, GPIO_INPUT); ccprints("fake hibernate. waits for power button/lid/RTC/AC"); cflush(); if (seconds || microseconds) { if (seconds) sleep(seconds); if (microseconds) usleep(microseconds); } else { while (1) task_wait_event(-1); } ccprints("fake RTC alarm fires. resets EC"); cflush(); system_reset(SYSTEM_RESET_HARD); }
bool wgraph::getedge(edge e, FILE* f) { // Read one edge from *f into edges[e]. Return true on success, else false. char c; if (cflush('(',f) == EOF) return false; fscanf(f,"%d",&edges[e].l); if (cflush(',',f) == EOF) return false; fscanf(f,"%d",&edges[e].r); if (cflush(',',f) == EOF) return false; fscanf(f,"%d",&edges[e].wt); if (cflush(')',f) == EOF) return false; return true; }
void addpersrc(void) { IMAGE_SECTION_HEADER *h; uchar *p; uint32 val; Reloc *r; if(rsrcsym == nil) return; h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0); h->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; // relocation for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) { p = rsrcsym->p + r->off; val = h->VirtualAddress + r->add; // 32-bit little-endian p[0] = val; p[1] = val>>8; p[2] = val>>16; p[3] = val>>24; } ewrite(cout, rsrcsym->p, rsrcsym->size); strnput("", h->SizeOfRawData - rsrcsym->size); cflush(); // update data directory dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize; }
static int command_reboot(int argc, char **argv) { int flags = 0; int i; for (i = 1; i < argc; i++) { if (!strcasecmp(argv[i], "hard") || !strcasecmp(argv[i], "cold")) { flags |= SYSTEM_RESET_HARD; } else if (!strcasecmp(argv[i], "soft")) { flags &= ~SYSTEM_RESET_HARD; } else if (!strcasecmp(argv[i], "ap-off")) { flags |= SYSTEM_RESET_LEAVE_AP_OFF; } else if (!strcasecmp(argv[i], "cancel")) { reboot_at_shutdown = EC_REBOOT_CANCEL; return EC_SUCCESS; } else if (!strcasecmp(argv[i], "preserve")) { flags |= SYSTEM_RESET_PRESERVE_FLAGS; } else return EC_ERROR_PARAM1 + i - 1; } if (flags & SYSTEM_RESET_HARD) ccputs("Hard-"); ccputs("Rebooting!\n\n\n"); cflush(); system_reset(flags); return EC_SUCCESS; }
static void board_handle_reboot(void) { int flags; if (system_jumped_to_this_image()) return; if (system_get_board_version() < BOARD_MIN_ID_LOD_EN) return; /* Interrogate current reset flags from previous reboot. */ flags = system_get_reset_flags(); if (!(flags & PMIC_RESET_FLAGS)) return; /* Preserve AP off request. */ if (flags & RESET_FLAG_AP_OFF) chip_save_reset_flags(RESET_FLAG_AP_OFF); ccprintf("Restarting system with PMIC.\n"); /* Flush console */ cflush(); /* Bring down all rails but RTC rail (including EC power). */ gpio_set_flags(GPIO_BATLOW_L_PMIC_LDO_EN, GPIO_OUT_HIGH); while (1) ; /* wait here */ }
static int command_gpio_get(int argc, char **argv) { int changed, v, i; /* If a signal is specified, print only that one */ if (argc == 2) { i = find_signal_by_name(argv[1]); if (i == GPIO_COUNT) return EC_ERROR_PARAM1; v = gpio_get_level(i); changed = last_val_changed(i, v); ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '), gpio_get_name(i)); return EC_SUCCESS; } /* Otherwise print them all */ for (i = 0; i < GPIO_COUNT; i++) { if (!gpio_is_implemented(i)) continue; /* Skip unsupported signals */ v = gpio_get_level(i); changed = last_val_changed(i, v); ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '), gpio_get_name(i)); /* Flush console to avoid truncating output */ cflush(); } return EC_SUCCESS; }
static void print_gpio_info(int gpio) { int changed, v, flags; if (!gpio_is_implemented(gpio)) return; /* Skip unsupported signals */ v = gpio_get_level(gpio); #ifdef CONFIG_CMD_GPIO_EXTENDED flags = gpio_get_flags(gpio); #else flags = 0; #endif changed = last_val_changed(gpio, v); ccprintf(" %d%c %s%s%s%s%s%s%s%s%s%s\n", v, (changed ? '*' : ' '), (flags & GPIO_INPUT ? "I " : ""), (flags & GPIO_OUTPUT ? "O " : ""), (flags & GPIO_LOW ? "L " : ""), (flags & GPIO_HIGH ? "H " : ""), (flags & GPIO_ANALOG ? "A " : ""), (flags & GPIO_OPEN_DRAIN ? "ODR " : ""), (flags & GPIO_PULL_UP ? "PU " : ""), (flags & GPIO_PULL_DOWN ? "PD " : ""), (flags & GPIO_ALTERNATE ? "ALT " : ""), gpio_get_name(gpio)); /* Flush console to avoid truncating output */ cflush(); }
void addexports(vlong fileoff) { IMAGE_SECTION_HEADER *sect; IMAGE_EXPORT_DIRECTORY e; int size, i, va, va_name, va_addr, va_na, v; size = sizeof e + 10*nexport + strlen(outfile) + 1; for(i=0; i<nexport; i++) size += strlen(dexport[i]->dynimpname) + 1; if (nexport == 0) return; sect = addpesection(".edata", size, size, 0); sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; va = sect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; seek(cout, fileoff, 0); va_name = va + sizeof e + nexport*4; va_addr = va + sizeof e; va_na = va + sizeof e + nexport*8; e.Characteristics = 0; e.MajorVersion = 0; e.MinorVersion = 0; e.NumberOfFunctions = nexport; e.NumberOfNames = nexport; e.Name = va + sizeof e + nexport*10; // Program names. e.Base = 1; e.AddressOfFunctions = va_addr; e.AddressOfNames = va_name; e.AddressOfNameOrdinals = va_na; // put IMAGE_EXPORT_DIRECTORY for (i=0; i<sizeof(e); i++) cput(((char*)&e)[i]); // put EXPORT Address Table for(i=0; i<nexport; i++) lputl(dexport[i]->value - PEBASE); // put EXPORT Name Pointer Table v = e.Name + strlen(outfile)+1; for(i=0; i<nexport; i++) { lputl(v); v += strlen(dexport[i]->dynimpname)+1; } // put EXPORT Ordinal Table for(i=0; i<nexport; i++) wputl(i); // put Names strnput(outfile, strlen(outfile)+1); for(i=0; i<nexport; i++) strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1); strnput("", sect->SizeOfRawData - size); cflush(); seek(cout, 0, 2); }
void kcputc(char ch) { CONSOLE_LOCK(kernel_output); cputc_noflush(kernel_output, ch); cflush(kernel_output); CONSOLE_UNLOCK(kernel_output); }
void kcputs(const char *s) { CONSOLE_LOCK(kernel_output); cputs_noflush(kernel_output, s, strlen(s)); cflush(kernel_output); CONSOLE_UNLOCK(kernel_output); }
void vprintf(const char *s, va_list ap) { CONSOLE_LOCK(kernel_output); kfvprintf(cputc_noflush, cputs_noflush, kernel_output, s, ap); cflush(kernel_output); CONSOLE_UNLOCK(kernel_output); }
void system_hibernate(uint32_t seconds, uint32_t microseconds) { /* Flush console before hibernating */ cflush(); /* chip specific standby mode */ CPRINTS("TODO: implement %s()", __func__); }
static void fake_hibernate_ac_hook(void) { if (fake_hibernate && extpower_is_present()) { ccprints("%s() resets EC", __func__); cflush(); system_reset(SYSTEM_RESET_HARD); } }
void kcputsn(const char *s, size_t len) { CONSOLE_LOCK(kernel_output); cputs_noflush(kernel_output, s, len); cflush(kernel_output); CONSOLE_UNLOCK(kernel_output); }
static void fake_hibernate_lid_hook(void) { if (fake_hibernate && lid_is_open()) { ccprints("%s() resets EC", __func__); cflush(); system_reset(SYSTEM_RESET_HARD); } }
void cput(int c) { cbp[0] = c; cbp++; cbc--; if(cbc <= 0) cflush(); }
static void cputc_noflush(void *arg, char ch) { struct console *console; console = arg; console->c_putc(console->c_softc, ch); if (ch == '\n') cflush(console); }
void cts_task(void) { enum cts_rc rc; int i; for (i = 0; i < CTS_TEST_ID_COUNT; i++) { sync(); rc = tests[i].run(); CPRINTF("\n%s %d\n", tests[i].name, rc); cflush(); } CPRINTS("Timer test suite finished"); cflush(); while (1) { watchdog_reload(); sleep(1); } }
void cts_task(void) { enum cts_rc rc; int i; task_wake(TASK_ID_TICK); for (i = 0; i < CTS_TEST_ID_COUNT; i++) { clear_state(); rc = tests[i].run(); CPRINTF("\n%s %d\n", tests[i].name, rc); cflush(); } CPRINTS("Task test suite finished"); cflush(); /* Sleep forever */ task_wait_event(-1); }
int timer_calib_task(void *data) { timestamp_t t0, t1; unsigned d; while (1) { task_wait_event(-1); ccprintf("\n=== Timer calibration ===\n"); t0 = get_time(); t1 = get_time(); ccprintf("- back-to-back get_time : %d us\n", difftime(t0, t1)); /* Sleep for 5 seconds */ ccprintf("- sleep 1s :\n "); cflush(); ccprintf("Go..."); t0 = get_time(); usleep(1000000); t1 = get_time(); ccprintf("done. delay = %d us\n", difftime(t0, t1)); /* try small usleep */ ccprintf("- short sleep :\n"); cflush(); for (d = 128; d > 0; d = d / 2) { t0 = get_time(); usleep(d); t1 = get_time(); ccprintf(" %d us => %d us\n", d, difftime(t0, t1)); cflush(); } ccprintf("Done.\n"); } return EC_SUCCESS; }
static void ir357x_dump(void) { int i; for (i = 0; i < 256; i++) { if (!(i & 0xf)) { ccprintf("\n%02x: ", i); cflush(); } ccprintf("%02x ", ir357x_read(i)); } ccprintf("\n"); }
static int command_mem_dump(int argc, char **argv) { uint32_t address, i, num = 1; char *e; enum format fmt = FMT_WORD; if (argc > 1) { if ((argv[1][0] == '.') && (strlen(argv[1]) == 2)) { switch (argv[1][1]) { case 'b': fmt = FMT_BYTE; break; case 'h': fmt = FMT_HALF; break; case 's': fmt = FMT_STRING; break; default: return EC_ERROR_PARAM1; } argc--; argv++; } } if (argc < 2) return EC_ERROR_PARAM_COUNT; address = strtoi(argv[1], &e, 0); if (*e) return EC_ERROR_PARAM1; if (argc >= 3) num = strtoi(argv[2], &e, 0); for (i = 0; i < num; i++) { show_val(address, i, fmt); /* Lots of output could take a while. * Let other things happen, too */ if (!(i % 0x100)) { watchdog_reload(); usleep(10 * MSEC); } } ccprintf("\n"); cflush(); return EC_SUCCESS; }
void cts_task(void) { enum cts_rc rc; int i; gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH); for (i = 0; i < CTS_TEST_ID_COUNT; i++) { gpio_set_level(GPIO_OUTPUT_TEST, 1); gpio_set_level(GPIO_CTS_IRQ2, 1); sync(); rc = tests[i].run(); CPRINTF("\n%s %d\n", tests[i].name, rc); cflush(); } CPRINTS("Interrupt test suite finished"); cflush(); while (1) { watchdog_reload(); sleep(1); } }
/** * Jump to what we hope is the init address of an image. * * This function does not return. * * @param init_addr Init address of target image */ static void jump_to_image(uintptr_t init_addr) { void (*resetvec)(void) = (void(*)(void))init_addr; /* * Jumping to any image asserts the signal to the Silego chip that that * EC is not in read-only firmware. (This is not technically true if * jumping from RO -> RO, but that's not a meaningful use case...). * * Pulse the signal long enough to set the latch in the Silego, then * drop it again so we don't leak power through the pulldown in the * Silego. */ gpio_set_level(GPIO_ENTERING_RW, 1); usleep(MSEC); gpio_set_level(GPIO_ENTERING_RW, 0); #if defined(CONFIG_I2C) && !defined(CONFIG_I2C_SLAVE_ONLY) /* Prepare I2C module for sysjump */ i2c_prepare_sysjump(); #endif /* Flush UART output */ cflush(); /* Disable interrupts before jump */ interrupt_disable(); #ifdef CONFIG_DMA /* Disable all DMA channels to avoid memory corruption */ dma_disable_all(); #endif /* CONFIG_DMA */ /* Fill in preserved data between jumps */ jdata->reserved0 = 0; jdata->magic = JUMP_DATA_MAGIC; jdata->version = JUMP_DATA_VERSION; jdata->reset_flags = reset_flags; jdata->jump_tag_total = 0; /* Reset tags */ jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP); /* Jump to the reset vector */ resetvec(); }
void board_hibernate(void) { CPRINTS("Enter Pseudo G3"); /* * Clean up the UART buffer and prevent any unwanted garbage characters * before power off and also ensure above debug message is printed. */ cflush(); gpio_set_level(GPIO_EC_HIB_L, 1); gpio_set_level(GPIO_SMC_SHUTDOWN, 1); /* Power to EC should shut down now */ while (1) ; }
static void pewrite(void) { seek(cout, 0, 0); ewrite(cout, dosstub, sizeof dosstub); strnput("PE", 4); cflush(); // TODO: This code should not assume that the // memory representation is little-endian or // that the structs are packed identically to // their file representation. ewrite(cout, &fh, sizeof fh); if(pe64) ewrite(cout, &oh64, sizeof oh64); else ewrite(cout, &oh, sizeof oh); ewrite(cout, &sh, nsect * sizeof sh[0]); }
static void blk(Sym *start, int32 addr, int32 size) { Sym *sym; int32 eaddr; uchar *p, *ep; for(sym = start; sym != nil; sym = sym->next) if(!(sym->type&SSUB) && sym->value >= addr) break; eaddr = addr+size; for(; sym != nil; sym = sym->next) { if(sym->type&SSUB) continue; if(sym->value >= eaddr) break; if(sym->value < addr) { diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type); errorexit(); } cursym = sym; for(; addr < sym->value; addr++) cput(0); p = sym->p; ep = p + sym->np; while(p < ep) cput(*p++); addr += sym->np; for(; addr < sym->value+sym->size; addr++) cput(0); if(addr != sym->value+sym->size) { diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size); errorexit(); } } for(; addr < eaddr; addr++) cput(0); cflush(); }