/* Return true if this partition is supported by the fastboot format command. * It is also used to determine if we should first erase a partition before * flashing it with an ext4 filesystem. See needs_erase() * * Not all devices report the filesystem type, so don't report any errors, * just return false. */ int fb_format_supported(usb_handle *usb, const char *partition) { char response[FB_RESPONSE_SZ+1]; struct generator *generator = NULL; int status; unsigned int i; status = fb_getvar(usb, response, "partition-type:%s", partition); if (status) { return 0; } for (i = 0; i < ARRAY_SIZE(generators); i++) { if (!strncmp(generators[i].fs_type, response, FB_RESPONSE_SZ)) { generator = &generators[i]; break; } } if (generator) { return 1; } return 0; }
static int64_t get_target_sparse_limit(struct usb_handle *usb) { int64_t limit = 0; char response[FB_RESPONSE_SZ + 1]; int status = fb_getvar(usb, response, "max-download-size"); if (!status) { limit = strtoul(response, NULL, 0); if (limit > 0) { fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", limit); } } return limit; }
static int64_t get_target_sparse_limit(transport_t *trans) { int64_t limit = 0; char response[FB_RESPONSE_SZ + 1]; int status = fb_getvar(trans, response, "max-download-size"); if (!status) { limit = strtoul(response, NULL, 0); if (limit > 0) { fprintf(stderr, "target reported max download size of %lld bytes\n", limit); } } return limit; }
void fb_perform_format(usb_handle* usb, const char *partition, int skip_if_not_supported, const char *type_override, const char *size_override) { char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1]; char *pType = pTypeBuff; char *pSize = pSizeBuff; unsigned int limit = INT_MAX; struct fastboot_buffer buf; const char *errMsg = NULL; const struct fs_generator *gen; uint64_t pSz; int status; int fd; if (target_sparse_limit > 0 && target_sparse_limit < limit) limit = target_sparse_limit; if (sparse_limit > 0 && sparse_limit < limit) limit = sparse_limit; status = fb_getvar(usb, pType, "partition-type:%s", partition); if (status) { errMsg = "Can't determine partition type.\n"; goto failed; } if (type_override) { if (strcmp(type_override, pType)) { fprintf(stderr, "Warning: %s type is %s, but %s was requested for formating.\n", partition, pType, type_override); } pType = (char *)type_override; } status = fb_getvar(usb, pSize, "partition-size:%s", partition); if (status) { errMsg = "Unable to get partition size\n"; goto failed; } if (size_override) { if (strcmp(size_override, pSize)) { fprintf(stderr, "Warning: %s size is %s, but %s was requested for formating.\n", partition, pSize, size_override); } pSize = (char *)size_override; } gen = fs_get_generator(pType); if (!gen) { if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); fprintf(stderr, "File system type %s not supported.\n", pType); return; } fprintf(stderr, "Formatting is not supported for filesystem with type '%s'.\n", pType); return; } pSz = strtoll(pSize, (char **)NULL, 16); fd = fileno(tmpfile()); if (fs_generator_generate(gen, fd, pSz)) { close(fd); fprintf(stderr, "Cannot generate image.\n"); return; } if (load_buf_fd(usb, fd, &buf)) { fprintf(stderr, "Cannot read image.\n"); close(fd); return; } flash_buf(partition, &buf); return; failed: if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); if (errMsg) fprintf(stderr, "%s", errMsg); } fprintf(stderr,"FAILED (%s)\n", fb_get_error()); }
int fb_format(Action *a, usb_handle *usb, int skip_if_not_supported) { const char *partition = a->cmd; char response[FB_RESPONSE_SZ+1]; int status = 0; struct image_data image; struct generator *generator = NULL; int fd; unsigned i; char cmd[CMD_SIZE]; status = fb_getvar(usb, response, "partition-type:%s", partition); if (status) { if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); fprintf(stderr, "Can't determine partition type.\n"); return 0; } fprintf(stderr,"FAILED (%s)\n", fb_get_error()); return status; } for (i = 0; i < ARRAY_SIZE(generators); i++) { if (!strncmp(generators[i].fs_type, response, FB_RESPONSE_SZ)) { generator = &generators[i]; break; } } if (!generator) { if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); fprintf(stderr, "File system type %s not supported.\n", response); return 0; } fprintf(stderr,"Formatting is not supported for filesystem with type '%s'.\n", response); return -1; } status = fb_getvar(usb, response, "partition-size:%s", partition); if (status) { if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); fprintf(stderr, "Unable to get partition size\n."); return 0; } fprintf(stderr,"FAILED (%s)\n", fb_get_error()); return status; } image.partition_size = strtoll(response, (char **)NULL, 16); generator->generate(&image); if (!image.buffer) { fprintf(stderr,"Cannot generate image.\n"); return -1; } // Following piece of code is similar to fb_queue_flash() but executes // actions directly without queuing fprintf(stderr, "sending '%s' (%lli KB)...\n", partition, image.image_size/1024); status = fb_download_data(usb, image.buffer, image.image_size); if (status) goto cleanup; fprintf(stderr, "writing '%s'...\n", partition); snprintf(cmd, sizeof(cmd), "flash:%s", partition); status = fb_command(usb, cmd); if (status) goto cleanup; cleanup: generator->cleanup(&image); return status; }
adv_error fb_mode_set(const fb_video_mode* mode) { unsigned req_xres; unsigned req_yres; unsigned req_bits_per_pixel; assert(fb_is_active() && !fb_mode_is_active()); log_std(("video:fb: fb_mode_set()\n")); log_std(("video:fb: get old\n")); /* get the current info */ if (fb_getvar(&fb_state.oldinfo, 0) != 0) { error_set("Error getting the variable video mode information.\n"); goto err; } fb_log(0, &fb_state.oldinfo); fb_preset(&fb_state.varinfo, mode->crtc.pixelclock, mode->crtc.hde, mode->crtc.hrs, mode->crtc.hre, mode->crtc.ht, mode->crtc.vde, mode->crtc.vrs, mode->crtc.vre, mode->crtc.vt, crtc_is_doublescan(&mode->crtc), crtc_is_interlace(&mode->crtc), crtc_is_nhsync(&mode->crtc), crtc_is_nvsync(&mode->crtc), mode->index, FB_ACTIVATE_NOW ); log_std(("video:fb: set new\n")); fb_log(0, &fb_state.varinfo); /* save the minimun required data */ req_xres = fb_state.varinfo.xres; req_yres = fb_state.varinfo.yres; req_bits_per_pixel = fb_state.varinfo.bits_per_pixel; /* set the mode */ if (fb_setvar(&fb_state.varinfo) != 0) { error_set("Error setting the variable video mode information.\n"); goto err; } log_std(("video:fb: get new\n")); /* get the fixed info */ if (fb_getfix(&fb_state.fixinfo) != 0) { error_set("Error getting the fixed video mode information.\n"); goto err_restore; } /* get the variable info */ if (fb_getvar(&fb_state.varinfo, mode->index) != 0) { error_set("Error getting the variable video mode information.\n"); goto err_restore; } fb_state.freq = fb_state.varinfo.pixclock; fb_state.freq *= fb_state.varinfo.xres + fb_state.varinfo.left_margin + fb_state.varinfo.right_margin + fb_state.varinfo.hsync_len; fb_state.freq *= fb_state.varinfo.yres + fb_state.varinfo.upper_margin + fb_state.varinfo.lower_margin + fb_state.varinfo.vsync_len; if (fb_state.freq != 0) { fb_state.freq = 1000000000000LL / fb_state.freq; } log_std(("video:fb: frequency %g\n", fb_state.freq)); fb_log(&fb_state.fixinfo, &fb_state.varinfo); /* check the validity of the resulting video mode */ if (req_xres > fb_state.varinfo.xres || req_yres > fb_state.varinfo.yres || req_bits_per_pixel != fb_state.varinfo.bits_per_pixel ) { log_std(("ERROR:video:fb: request for mode %dx%d %d bits resulted in mode %dx%dx %d bits\n", req_xres, req_yres, req_bits_per_pixel, fb_state.varinfo.xres, fb_state.varinfo.yres, fb_state.varinfo.bits_per_pixel)); error_set("Error setting the requested video mode.\n"); goto err_restore; } if (req_xres != fb_state.varinfo.xres || req_yres != fb_state.varinfo.yres ) { /* allow bigger modes */ log_std(("WARNING:video:fb: request for mode %dx%d resulted in mode %dx%dx\n", req_xres, req_yres, fb_state.varinfo.xres, fb_state.varinfo.yres)); } if (fb_setup_color() != 0) { error_set("Error setting the color information.\n"); goto err_restore; } fb_write_line = fb_linear_write_line; fb_state.bytes_per_pixel = (fb_state.varinfo.bits_per_pixel + 7) / 8; fb_state.bytes_per_scanline = fb_state.fixinfo.line_length; fb_state.index = mode->index; fb_state.ptr = mmap(0, fb_state.fixinfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_state.fd, 0 ); if (fb_state.ptr == MAP_FAILED) { error_set("Error mapping the video memory.\n"); goto err_restore; } fb_state.wait_last = 0; fb_state.wait = fb_wait_detect; /* reset the wait mode */ fb_state.wait_error = 0; fb_state.mode_active = 1; return 0; err_restore: fb_setvar(&fb_state.oldinfo); /* ignore error */ err: return -1; }
adv_error fb_init(int device_id, adv_output output, unsigned overlay_size, adv_cursor cursor) { const char* fb; char id_buffer[64]; char* term; (void)cursor; (void)overlay_size; assert(!fb_is_active()); log_std(("video:fb: fb_init()\n")); if (sizeof(fb_video_mode) > MODE_DRIVER_MODE_SIZE_MAX) return -1; if (os_internal_wm_active()) { error_set("Unsupported in X. Try with the SDL library.\n"); return -1; } term = getenv("TERM"); if (!term || strcmp(term, "linux")!=0) { error_set("Works only with TERM=linux terminals.\n"); return -1; } if (output != adv_output_auto && output != adv_output_fullscreen) { error_set("Only fullscreen output is supported.\n"); return -1; } fb = getenv("FRAMEBUFFER"); if (fb && fb[0]) { fb_state.fd = open(fb, O_RDWR); } else { fb = "/dev/fb0"; fb_state.fd = open(fb, O_RDWR); if (fb_state.fd < 0 && errno == ENOENT) { fb = "/dev/fb/0"; fb_state.fd = open(fb, O_RDWR); } } if (fb_state.fd < 0) { if (errno == ENODEV) { error_set("Video board not supported. Error %d (%s).\n", errno, strerror(errno)); } else { error_set("Error opening the frame buffer %s. Error %d (%s).\n", fb, errno, strerror(errno)); } return -1; } /* get the fixed info */ if (fb_getfix(&fb_state.fixinfo) != 0) { error_set("Error getting the fixed video mode information.\n"); goto err_close; } /* get the variable info */ if (fb_getvar(&fb_state.varinfo, 0) != 0) { error_set("Error getting the variable video mode information.\n"); goto err_close; } /* copy the id in a safe way, it may be not 0 terminated */ sncpyn(id_buffer, sizeof(id_buffer), fb_state.fixinfo.id, sizeof(fb_state.fixinfo.id)); log_std(("video:fb: id %s\n", id_buffer)); fb_log(&fb_state.fixinfo, &fb_state.varinfo); if (strcmp(id_buffer, "VESA VGA")==0) { error_set("The 'vesafb' FrameBuffer driver doesn't allow the creation of new video modes.\n"); goto err_close; } fb_state.flags = VIDEO_DRIVER_FLAGS_MODE_PALETTE8 | VIDEO_DRIVER_FLAGS_MODE_BGR15 | VIDEO_DRIVER_FLAGS_MODE_BGR16 | VIDEO_DRIVER_FLAGS_MODE_BGR24 | VIDEO_DRIVER_FLAGS_MODE_BGR32 | VIDEO_DRIVER_FLAGS_PROGRAMMABLE_ALL | VIDEO_DRIVER_FLAGS_OUTPUT_FULLSCREEN; if (fb_detect() != 0) { goto err_close; } if ((fb_state.flags & (VIDEO_DRIVER_FLAGS_MODE_PALETTE8 | VIDEO_DRIVER_FLAGS_MODE_BGR15 | VIDEO_DRIVER_FLAGS_MODE_BGR16 | VIDEO_DRIVER_FLAGS_MODE_BGR24 | VIDEO_DRIVER_FLAGS_MODE_BGR32)) == 0) { error_set("This '%s' FrameBuffer driver doesn't seem to allow the creation of new video modes.\n", id_buffer); goto err_close; } fb_state.active = 1; return 0; err_close: close(fb_state.fd); return -1; }