void pic_remap(uint8_t irq0_offset, uint8_t irq8_offset) { unsigned char mask1, mask2; mask1 = port_read_8(PIC_MASTER_DATA_PORT); mask2 = port_read_8(PIC_SLAVE_DATA_PORT); port_write_8(PIC_MASTER_COMMAND_PORT, 0x11); port_wait(); port_write_8(PIC_SLAVE_COMMAND_PORT, 0x11); port_wait(); port_write_8(PIC_MASTER_DATA_PORT, irq0_offset); port_wait(); port_write_8(PIC_SLAVE_DATA_PORT, irq8_offset); port_wait(); port_write_8(PIC_MASTER_DATA_PORT, 4); port_wait(); port_write_8(PIC_SLAVE_DATA_PORT, 2); port_wait(); port_write_8(PIC_MASTER_DATA_PORT, 1); port_wait(); port_write_8(PIC_SLAVE_DATA_PORT, 1); port_wait(); port_write_8(PIC_MASTER_DATA_PORT, mask1); port_write_8(PIC_SLAVE_DATA_PORT, mask2); }
void set_log_listener_active(bool active) { if (active) { port_wait(&port, &log_ph); } else { port_cancel(&port, &log_ph); } }
static void setup_dir_watcher(const char* dir, zx_status_t (*cb)(port_handler_t*, zx_signals_t, uint32_t), port_handler_t* ph, int* fd_out) { *fd_out = -1; fbl::unique_fd fd(open(dir, O_DIRECTORY | O_RDONLY)); if (!fd) { return; } zx::channel client, server; if (zx::channel::create(0, &client, &server) != ZX_OK) { return; } fzl::FdioCaller caller(std::move(fd)); zx_status_t status; zx_status_t io_status = fuchsia_io_DirectoryWatch(caller.borrow_channel(), fuchsia_io_WATCH_MASK_ALL, 0, server.release(), &status); if (io_status != ZX_OK || status != ZX_OK) { return; } *fd_out = caller.release().release(); ph->handle = client.release(); ph->waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; ph->func = cb; port_wait(&port, ph); }
static zx_status_t new_vc_cb(port_handler_t* ph, zx_signals_t signals, uint32_t evt) { zx_handle_t h; uint32_t dcount, hcount; if (zx_channel_read(ph->handle, 0, NULL, &h, 0, 1, &dcount, &hcount) < 0) { return ZX_OK; } if (hcount != 1) { return ZX_OK; } vc_t* vc; int fd; if (session_create(&vc, &fd, true, false) < 0) { zx_handle_close(h); return ZX_OK; } zx_handle_t handles[FDIO_MAX_HANDLES]; uint32_t types[FDIO_MAX_HANDLES]; zx_status_t r = fdio_transfer_fd(fd, FDIO_FLAG_USE_FOR_STDIO | 0, handles, types); if (zx_channel_write(h, 0, types, static_cast<uint32_t>(r * sizeof(uint32_t)), handles, r) != ZX_OK) { session_destroy(vc); } else { port_wait(&port, &vc->fh.ph); } zx_handle_close(h); return ZX_OK; }
int main(int argc, char** argv) { // NOTE: devmgr has getenv_bool. when more options are added, consider // sharing that. bool keep_log = false; const char* value = getenv("virtcon.keep-log-visible"); if (value == NULL || ((strcmp(value, "0") == 0) || (strcmp(value, "false") == 0) || (strcmp(value, "off") == 0))) { keep_log = false; } else { keep_log = true; } const char* cmd = NULL; int shells = 0; while (argc > 1) { if (!strcmp(argv[1], "--run")) { if (argc > 2) { argc--; argv++; cmd = argv[1]; if (shells < 1) shells = 1; printf("CMD: %s\n", cmd); } } else if (!strcmp(argv[1], "--shells")) { if (argc > 2) { argc--; argv++; shells = atoi(argv[1]); } } argc--; argv++; } if (port_init(&port) < 0) { return -1; } // create initial console for debug log if (vc_create(&log_vc, false) != ZX_OK) { return -1; } snprintf(log_vc->title, sizeof(log_vc->title), "debuglog"); // Get our process koid so the log reader can // filter out our own debug messages from the log zx_info_handle_basic_t info; if (zx_object_get_info(zx_process_self(), ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL) == ZX_OK) { proc_koid = info.koid; } log_ph.handle = zx_take_startup_handle(PA_HND(PA_USER0, 1)); if (log_ph.handle == ZX_HANDLE_INVALID) { printf("vc log listener: did not receive log startup handle\n"); return -1; } log_ph.func = log_reader_cb; log_ph.waitfor = ZX_LOG_READABLE; if ((new_vc_ph.handle = zx_take_startup_handle(PA_HND(PA_USER0, 0))) != ZX_HANDLE_INVALID) { new_vc_ph.func = new_vc_cb; new_vc_ph.waitfor = ZX_CHANNEL_READABLE; port_wait(&port, &new_vc_ph); } setup_dir_watcher("/dev/class/input", input_cb, &input_ph, &input_dir_fd); if (!vc_display_init()) { return -1; } setenv("TERM", "xterm", 1); for (int i = 0; i < shells; ++i) { if (i == 0) start_shell(!keep_log, cmd); else start_shell(false, NULL); } zx_status_t r = port_dispatch(&port, ZX_TIME_INFINITE, false); printf("vc: port failure: %d\n", r); return -1; }
static zx_status_t session_create(vc_t** out, int* out_fd, bool make_active, bool special) { int fd; // The ptmx device can start later than these threads int retry = 30; while ((fd = open("/dev/misc/ptmx", O_RDWR | O_NONBLOCK)) < 0) { if (--retry == 0) { return ZX_ERR_IO; } usleep(100000); } int client_fd = openat(fd, "0", O_RDWR); if (client_fd < 0) { close(fd); return ZX_ERR_IO; } vc_t* vc; if (vc_create(&vc, special)) { close(fd); close(client_fd); return ZX_ERR_INTERNAL; } zx_status_t r; if ((r = port_fd_handler_init(&vc->fh, fd, POLLIN | POLLRDHUP | POLLHUP)) < 0) { vc_destroy(vc); close(fd); close(client_fd); return r; } vc->fd = fd; if (make_active) { vc_set_active(-1, vc); } pty_window_size_t wsz = { .width = vc->columns, .height = vc->rows, }; ioctl_pty_set_window_size(fd, &wsz); vc->fh.func = session_io_cb; *out = vc; *out_fd = client_fd; return ZX_OK; } static void start_shell(bool make_active, const char* cmd) { vc_t* vc; int fd; if (session_create(&vc, &fd, make_active, cmd != NULL) < 0) { return; } vc->is_shell = true; if (launch_shell(vc, fd, cmd) < 0) { session_destroy(vc); } else { port_wait(&port, &vc->fh.ph); } }