char *libxl__domid_to_name(libxl__gc *gc, uint32_t domid) { char *s = libxl_domid_to_name(libxl__gc_owner(gc), domid); if ( s ) libxl__ptr_add(gc, s); return s; }
char *libxl__cpupoolid_to_name(libxl__gc *gc, uint32_t poolid) { char *s = libxl_cpupoolid_to_name(libxl__gc_owner(gc), poolid); if ( s ) libxl__ptr_add(gc, s); return s; }
void *libxl__calloc(libxl__gc *gc, size_t nmemb, size_t size) { void *ptr = calloc(nmemb, size); if (!ptr) libxl__alloc_failed(CTX, __func__, nmemb, size); libxl__ptr_add(gc, ptr); return ptr; }
void *libxl__zalloc(libxl__gc *gc, int bytes) { void *ptr = calloc(bytes, 1); if (!ptr) libxl__alloc_failed(CTX, __func__, bytes, 1); libxl__ptr_add(gc, ptr); return ptr; }
void *libxl__malloc(libxl__gc *gc, size_t size) { void *ptr = malloc(size); if (!ptr) libxl__alloc_failed(CTX, __func__, size, 1); libxl__ptr_add(gc, ptr); return ptr; }
char *libxl__strdup(libxl__gc *gc, const char *c) { char *s = strdup(c); if (s) libxl__ptr_add(gc, s); return s; }
char *libxl__strndup(libxl__gc *gc, const char *c, size_t n) { char *s = strndup(c, n); if (!s) libxl__alloc_failed(CTX, __func__, n, 1); libxl__ptr_add(gc, s); return s; }
char *libxl__strdup(libxl__gc *gc, const char *c) { char *s = strdup(c); if (!s) libxl__alloc_failed(CTX, __func__, strlen(c), 1); libxl__ptr_add(gc, s); return s; }
void *libxl__calloc(libxl__gc *gc, size_t nmemb, size_t size) { void *ptr = calloc(nmemb, size); if (!ptr) { libxl__error_set(libxl__gc_owner(gc), ENOMEM); return NULL; } libxl__ptr_add(gc, ptr); return ptr; }
void *libxl__zalloc(libxl__gc *gc, int bytes) { void *ptr = calloc(bytes, 1); if (!ptr) { libxl__error_set(libxl__gc_owner(gc), ENOMEM); return NULL; } libxl__ptr_add(gc, ptr); return ptr; }
void *libxl__realloc(libxl__gc *gc, void *ptr, size_t new_size) { void *new_ptr = realloc(ptr, new_size); int i = 0; if (new_ptr == NULL && new_size != 0) libxl__alloc_failed(CTX, __func__, new_size, 1); if (ptr == NULL) { libxl__ptr_add(gc, new_ptr); } else if (new_ptr != ptr && libxl__gc_is_real(gc)) { for (i = 0; i < gc->alloc_maxsize; i++) { if (gc->alloc_ptrs[i] == ptr) { gc->alloc_ptrs[i] = new_ptr; break; } } } return new_ptr; }
void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl) { STATE_AO_GC(bl->ao); const libxl_domain_build_info *info = bl->info; uint32_t domid = bl->domid; char *logfile_tmp = NULL; int rc, r; libxl__bootloader_init(bl); if (info->type != LIBXL_DOMAIN_TYPE_PV) { LOG(DEBUG, "not a PV domain, skipping bootloader"); rc = 0; goto out_ok; } if (!info->u.pv.bootloader) { LOG(DEBUG, "no bootloader configured, using user supplied kernel"); bl->kernel->path = bl->info->u.pv.kernel; bl->ramdisk->path = bl->info->u.pv.ramdisk; bl->cmdline = bl->info->u.pv.cmdline; rc = 0; goto out_ok; } if (!bl->disk) { LOG(ERROR, "cannot run bootloader with no boot disk"); rc = ERROR_FAIL; goto out; } bootloader_setpaths(gc, bl); const char *logfile_leaf = GCSPRINTF("bootloader.%"PRIu32, domid); rc = libxl_create_logfile(CTX, logfile_leaf, &logfile_tmp); if (rc) goto out; /* Transfer ownership of log filename to bl and the gc */ bl->logfile = logfile_tmp; libxl__ptr_add(gc, logfile_tmp); logfile_tmp = NULL; bl->display.log = fopen(bl->logfile, "a"); if (!bl->display.log) { LOGE(ERROR, "failed to create bootloader logfile %s", bl->logfile); rc = ERROR_FAIL; goto out; } for (;;) { r = mkdir(bl->outputdir, 0600); if (!r) break; if (errno == EINTR) continue; if (errno == EEXIST) break; LOGE(ERROR, "failed to create bootloader dir %s", bl->outputdir); rc = ERROR_FAIL; goto out; } for (;;) { r = open(bl->outputpath, O_WRONLY|O_CREAT|O_TRUNC, 0600); if (r>=0) { close(r); break; } if (errno == EINTR) continue; LOGE(ERROR, "failed to precreate bootloader output %s", bl->outputpath); rc = ERROR_FAIL; goto out; } /* This sets the state of the dls struct from Undefined to Idle */ libxl__device_disk_local_init(&bl->dls); bl->dls.ao = ao; bl->dls.in_disk = bl->disk; bl->dls.blkdev_start = info->blkdev_start; bl->dls.callback = bootloader_disk_attached_cb; libxl__device_disk_local_initiate_attach(egc, &bl->dls); return; out: assert(rc); out_ok: free(logfile_tmp); bootloader_callback(egc, bl, rc); }
/* * filedescriptors: * fifo_fd - bootstring output from the bootloader * xenconsoled_fd - input/output from/to xenconsole * bootloader_fd - input/output from/to pty that controls the bootloader * The filedescriptors are NDELAY, so it's ok to try to read * bigger chunks than may be available, to keep e.g. curses * screen redraws in the bootloader efficient. xenconsoled_fd is the side that * gets xenconsole input, which will be keystrokes, so a small number * is sufficient. bootloader_fd is pygrub output, which will be curses screen * updates, so a larger number (1024) is appropriate there. * * For writeable descriptors, only include them in the set for select * if there is actual data to write, otherwise this would loop too fast, * eating up CPU time. */ static char * bootloader_interact(libxl__gc *gc, int xenconsoled_fd, int bootloader_fd, int fifo_fd) { int ret; size_t nr_out = 0, size_out = 0; char *output = NULL; /* input from xenconsole. read on xenconsoled_fd write to bootloader_fd */ int xenconsoled_prod = 0, xenconsoled_cons = 0; char xenconsoled_buf[XENCONSOLED_BUF_SIZE]; /* output from bootloader. read on bootloader_fd write to xenconsoled_fd */ int bootloader_prod = 0, bootloader_cons = 0; char bootloader_buf[BOOTLOADER_BUF_SIZE]; while(1) { fd_set wsel, rsel; int nfds; if (xenconsoled_prod == xenconsoled_cons) xenconsoled_prod = xenconsoled_cons = 0; if (bootloader_prod == bootloader_cons) bootloader_prod = bootloader_cons = 0; FD_ZERO(&rsel); FD_SET(fifo_fd, &rsel); nfds = fifo_fd + 1; if (xenconsoled_prod == 0 || (xenconsoled_prod < BOOTLOADER_BUF_SIZE && xenconsoled_cons == 0)) { FD_SET(xenconsoled_fd, &rsel); nfds = xenconsoled_fd + 1 > nfds ? xenconsoled_fd + 1 : nfds; } if (bootloader_prod == 0 || (bootloader_prod < BOOTLOADER_BUF_SIZE && bootloader_cons == 0)) { FD_SET(bootloader_fd, &rsel); nfds = bootloader_fd + 1 > nfds ? bootloader_fd + 1 : nfds; } FD_ZERO(&wsel); if (bootloader_prod != bootloader_cons) { FD_SET(xenconsoled_fd, &wsel); nfds = xenconsoled_fd + 1 > nfds ? xenconsoled_fd + 1 : nfds; } if (xenconsoled_prod != xenconsoled_cons) { FD_SET(bootloader_fd, &wsel); nfds = bootloader_fd + 1 > nfds ? bootloader_fd + 1 : nfds; } ret = select(nfds, &rsel, &wsel, NULL, NULL); if (ret < 0) goto out_err; /* Input from xenconsole, read xenconsoled_fd, write bootloader_fd */ if (FD_ISSET(xenconsoled_fd, &rsel)) { ret = read(xenconsoled_fd, &xenconsoled_buf[xenconsoled_prod], XENCONSOLED_BUF_SIZE - xenconsoled_prod); if (ret < 0 && errno != EIO && errno != EAGAIN) goto out_err; if (ret > 0) xenconsoled_prod += ret; } if (FD_ISSET(bootloader_fd, &wsel)) { ret = write(bootloader_fd, &xenconsoled_buf[xenconsoled_cons], xenconsoled_prod - xenconsoled_cons); if (ret < 0 && errno != EIO && errno != EAGAIN) goto out_err; if (ret > 0) xenconsoled_cons += ret; } /* Input from bootloader, read bootloader_fd, write xenconsoled_fd */ if (FD_ISSET(bootloader_fd, &rsel)) { ret = read(bootloader_fd, &bootloader_buf[bootloader_prod], BOOTLOADER_BUF_SIZE - bootloader_prod); if (ret < 0 && errno != EIO && errno != EAGAIN) goto out_err; if (ret > 0) bootloader_prod += ret; } if (FD_ISSET(xenconsoled_fd, &wsel)) { ret = write(xenconsoled_fd, &bootloader_buf[bootloader_cons], bootloader_prod - bootloader_cons); if (ret < 0 && errno != EIO && errno != EAGAIN) goto out_err; if (ret > 0) bootloader_cons += ret; } if (FD_ISSET(fifo_fd, &rsel)) { if (size_out - nr_out < 256) { char *temp; size_t new_size = size_out == 0 ? 32 : size_out * 2; temp = realloc(output, new_size); if (temp == NULL) goto out_err; output = temp; memset(output + size_out, 0, new_size - size_out); size_out = new_size; } ret = read(fifo_fd, output + nr_out, size_out - nr_out); if (ret > 0) nr_out += ret; if (ret == 0) break; } } libxl__ptr_add(gc, output); return output; out_err: free(output); return NULL; }
char *libxl__domid_to_name(libxl__gc *gc, uint32_t domid) { char *s = libxl_domid_to_name(CTX, domid); libxl__ptr_add(gc, s); return s; }
char *libxl__cpupoolid_to_name(libxl__gc *gc, uint32_t poolid) { char *s = libxl_cpupoolid_to_name(CTX, poolid); libxl__ptr_add(gc, s); return s; }