diff options
-rw-r--r-- | NOTICE | 27 | ||||
-rw-r--r-- | install/Android.bp | 1 | ||||
-rw-r--r-- | install/fuse_install.cpp | 80 | ||||
-rw-r--r-- | install/install.cpp | 4 | ||||
-rw-r--r-- | minui/graphics_drm.cpp | 499 | ||||
-rw-r--r-- | minui/graphics_drm.h | 35 | ||||
-rw-r--r-- | recovery.cpp | 109 | ||||
-rw-r--r-- | recovery_utils/roots.cpp | 3 |
8 files changed, 684 insertions, 74 deletions
@@ -9,7 +9,32 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - +________________________________________________________________________________ + + DRM based mode setting test program + Copyright 2008 Tungsten Graphics + Jakob Bornecrantz <jakob@tungstengraphics.com> + Copyright 2008 Intel Corporation + Jesse Barnes <jesse.barnes@intel.com> + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +________________________________________________________________________________ Apache License Version 2.0, January 2004 diff --git a/install/Android.bp b/install/Android.bp index e239ddc4..3a6581f6 100644 --- a/install/Android.bp +++ b/install/Android.bp @@ -33,6 +33,7 @@ cc_defaults { "libbase", "libbootloader_message", "libcrypto", + "libcutils", "libext4_utils", "libfs_mgr", "libfusesideload", diff --git a/install/fuse_install.cpp b/install/fuse_install.cpp index 143b5d3f..91d5d1bd 100644 --- a/install/fuse_install.cpp +++ b/install/fuse_install.cpp @@ -30,8 +30,10 @@ #include <string> #include <vector> +#include <android-base/file.h> #include <android-base/logging.h> #include <android-base/strings.h> +#include <cutils/properties.h> #include "bootloader_message/bootloader_message.h" #include "fuse_provider.h" @@ -39,6 +41,11 @@ #include "install/install.h" #include "recovery_utils/roots.h" +#define MMC_0_TYPE_PATH "/sys/block/mmcblk0/device/type" +#define SDCARD_BLK_0_PATH "/dev/block/mmcblk0p1" +#define MMC_1_TYPE_PATH "/sys/block/mmcblk1/device/type" +#define SDCARD_BLK_1_PATH "/dev/block/mmcblk1p1" + static constexpr const char* SDCARD_ROOT = "/sdcard"; // How long (in seconds) we wait for the fuse-provided package file to // appear, before timing out. @@ -204,10 +211,79 @@ InstallResult InstallWithFuseFromPath(std::string_view path, RecoveryUI* ui) { return result; } +// Check whether the mmc type of provided path (/sys/block/mmcblk*/device/type) +// is SD (sdcard) or not. +static int check_mmc_is_sdcard (const char* mmc_type_path) +{ + std::string mmc_type; + + LOG(INFO) << "Checking mmc type for path : " << mmc_type_path; + + if (!android::base::ReadFileToString(mmc_type_path, &mmc_type)) { + LOG(ERROR) << "Failed to read mmc type : " << strerror(errno); + return -1; + } + LOG(INFO) << "MMC type is : " << mmc_type.c_str(); + if (!strncmp(mmc_type.c_str(), "SD", strlen("SD"))) + return 0; + else + return -1; +} + +// Gather mount point and other info from fstab, find the right block +// path where sdcard is mounted, and try mounting it. +static int do_sdcard_mount() { + int rc = 0; + + Volume *v = volume_for_mount_point("/sdcard"); + if (v == nullptr) { + LOG(ERROR) << "Unknown volume for /sdcard. Check fstab\n"; + goto error; + } + if (strncmp(v->fs_type.c_str(), "vfat", sizeof("vfat"))) { + LOG(ERROR) << "Unsupported format on the sdcard: " + << v->fs_type.c_str() << "\n"; + goto error; + } + + if (check_mmc_is_sdcard(MMC_0_TYPE_PATH) == 0) { + LOG(INFO) << "Mounting sdcard on " << SDCARD_BLK_0_PATH; + rc = mount(SDCARD_BLK_0_PATH, + v->mount_point.c_str(), + v->fs_type.c_str(), + v->flags, + v->fs_options.c_str()); + } + else if (check_mmc_is_sdcard(MMC_1_TYPE_PATH) == 0) { + LOG(INFO) << "Mounting sdcard on " << SDCARD_BLK_1_PATH; + rc = mount(SDCARD_BLK_1_PATH, + v->mount_point.c_str(), + v->fs_type.c_str(), + v->flags, + v->fs_options.c_str()); + } + else { + LOG(ERROR) << "Unable to get the block path for sdcard."; + goto error; + } + + if (rc) { + LOG(ERROR) << "Failed to mount sdcard: " << strerror(errno) << "\n"; + goto error; + } + LOG(INFO) << "Done mounting sdcard\n"; + return 0; + +error: + return -1; +} + InstallResult ApplyFromSdcard(Device* device) { auto ui = device->GetUI(); - if (ensure_path_mounted(SDCARD_ROOT) != 0) { - LOG(ERROR) << "\n-- Couldn't mount " << SDCARD_ROOT << ".\n"; + ui->Print("Update via sdcard. Mounting sdcard\n"); + + if (do_sdcard_mount() != 0) { + LOG(ERROR) << "\nFailed to mount sdcard\n"; return INSTALL_ERROR; } diff --git a/install/install.cpp b/install/install.cpp index 6e74f80a..b9b3913e 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -712,7 +712,9 @@ bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse) { } constexpr const char* CACHE_ROOT = "/cache"; - if (android::base::StartsWith(package_path, CACHE_ROOT)) { + constexpr const char* DATA_ROOT = "/data"; + if (android::base::StartsWith(package_path, CACHE_ROOT) || + android::base::StartsWith(package_path, DATA_ROOT)) { *should_use_fuse = false; } return true; diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp index 95759e38..17ab00af 100644 --- a/minui/graphics_drm.cpp +++ b/minui/graphics_drm.cpp @@ -14,8 +14,35 @@ * limitations under the License. */ +/* + * DRM based mode setting test program + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + #include "graphics_drm.h" +#include <errno.h> #include <fcntl.h> #include <poll.h> #include <stdio.h> @@ -29,12 +56,256 @@ #include <android-base/macros.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> +#include <string> #include <drm_fourcc.h> #include <xf86drm.h> #include <xf86drmMode.h> +#include <sstream> #include "minui/minui.h" +#define find_prop_id(_res, type, Type, obj_id, prop_name, prop_id) \ + do { \ + int j = 0; \ + int prop_count = 0; \ + struct Type *obj = NULL; \ + obj = (_res); \ + if (!obj || main_monitor_##type->type##_id != (obj_id)){ \ + prop_id = 0; \ + break; \ + } \ + prop_count = (int)obj->props->count_props; \ + for (j = 0; j < prop_count; ++j) \ + if (!strcmp(obj->props_info[j]->name, (prop_name))) \ + break; \ + (prop_id) = (j == prop_count)? \ + 0 : obj->props_info[j]->prop_id; \ + } while (0) + +#define add_prop(res, type, Type, id, id_name, id_val) \ + find_prop_id(res, type, Type, id, id_name, prop_id); \ + if (prop_id) \ + drmModeAtomicAddProperty(atomic_req, id, prop_id, id_val); + +/** + * enum sde_rm_topology_name - HW resource use case in use by connector + * @SDE_RM_TOPOLOGY_NONE: No topology in use currently + * @SDE_RM_TOPOLOGY_SINGLEPIPE: 1 LM, 1 PP, 1 INTF/WB + * @SDE_RM_TOPOLOGY_SINGLEPIPE_DSC: 1 LM, 1 DSC, 1 PP, 1 INTF/WB + * @SDE_RM_TOPOLOGY_SINGLEPIPE_VDC: 1 LM, 1 VDC, 1 PP, 1 INTF/WB + * @SDE_RM_TOPOLOGY_DUALPIPE: 2 LM, 2 PP, 2 INTF/WB + * @SDE_RM_TOPOLOGY_DUALPIPE_DSC: 2 LM, 2 DSC, 2 PP, 2 INTF/WB + * @SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE: 2 LM, 2 PP, 3DMux, 1 INTF/WB + * @SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC: 2 LM, 2 PP, 3DMux, 1 DSC, 1 INTF/WB + * @SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_VDC: 2 LM, 2 PP, 3DMux, 1 VDC, 1 INTF/WB + * @SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE: 2 LM, 2 PP, 2 DSC Merge, 1 INTF/WB + * @SDE_RM_TOPOLOGY_PPSPLIT: 1 LM, 2 PPs, 2 INTF/WB + * @SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE 4 LM, 4 PP, 3DMux, 2 INTF + * @SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE_DSC 4 LM, 4 PP, 3DMux, 3 DSC, 2 INTF + * @SDE_RM_TOPOLOGY_QUADPIPE_DSCMERE 4 LM, 4 PP, 4 DSC Merge, 2 INTF + * @SDE_RM_TOPOLOGY_QUADPIPE_DSC4HSMERGE 4 LM, 4 PP, 4 DSC Merge, 1 INTF + */ + +static uint32_t get_lm_number(const std::string &topology) { + if (topology == "sde_singlepipe") return 1; + if (topology == "sde_singlepipe_dsc") return 1; + if (topology == "sde_singlepipe_vdc") return 1; + if (topology == "sde_dualpipe") return 2; + if (topology == "sde_dualpipe_dsc") return 2; + if (topology == "sde_dualpipe_vdc") return 2; + if (topology == "sde_dualpipemerge") return 2; + if (topology == "sde_dualpipemerge_dsc") return 2; + if (topology == "sde_dualpipemerge_vdc") return 2; + if (topology == "sde_dualpipe_dscmerge") return 2; + if (topology == "sde_ppsplit") return 1; + if (topology == "sde_quadpipemerge") return 4; + if (topology == "sde_quadpipe_3dmerge_dsc") return 4; + if (topology == "sde_quadpipe_dscmerge") return 4; + if (topology == "sde_quadpipe_dsc4hsmerge") return 4; + return DEFAULT_NUM_LMS; +} + +static uint32_t get_topology_lm_number(int fd, uint32_t blob_id) { + uint32_t num_lm = DEFAULT_NUM_LMS; + + drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd, blob_id); + if (!blob) { + return num_lm; + } + + const char *fmt_str = (const char *)(blob->data); + std::stringstream stream(fmt_str); + std::string line = {}; + const std::string topology = "topology="; + + while (std::getline(stream, line)) { + if (line.find(topology) != std::string::npos) { + num_lm = get_lm_number(std::string(line, topology.length())); + break; + } + } + + drmModeFreePropertyBlob(blob); + return num_lm; +} + +static int find_plane_prop_id(uint32_t obj_id, const char *prop_name, + Plane *plane_res) { + int i, j = 0; + int prop_count = 0; + struct Plane *obj = NULL; + + for (i = 0; i < NUM_PLANES; ++i) { + obj = &plane_res[i]; + if (!obj || obj->plane->plane_id != obj_id) + continue; + prop_count = (int)obj->props->count_props; + for (j = 0; j < prop_count; ++j) + if (!strcmp(obj->props_info[j]->name, prop_name)) + return obj->props_info[j]->prop_id; + break; + } + + return 0; +} + +static int atomic_add_prop_to_plane(Plane *plane_res, drmModeAtomicReq *req, + uint32_t obj_id, const char *prop_name, + uint64_t value) { + uint32_t prop_id; + + prop_id = find_plane_prop_id(obj_id, prop_name, plane_res); + if (prop_id == 0) { + printf("Could not find obj_id = %d\n", obj_id); + return -EINVAL; + } + + if (drmModeAtomicAddProperty(req, obj_id, prop_id, value) < 0) { + printf("Could not add prop_id = %d for obj_id %d\n", + prop_id, obj_id); + return -EINVAL; + } + + return 0; +} + +int MinuiBackendDrm::AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_req) { + uint32_t src_x, src_y, src_w, src_h; + uint32_t crtc_x, crtc_y, crtc_w, crtc_h; + int width = main_monitor_crtc->mode.hdisplay; + int height = main_monitor_crtc->mode.vdisplay; + int zpos = 0; + + src_y = 0; + src_w = width/number_of_lms; + src_h = height; + crtc_y = 0; + crtc_w = width/number_of_lms; + crtc_h = height; + src_x = (width/number_of_lms) * plane; + crtc_x = (width/number_of_lms) * plane; + + /* populate z-order property required for 4 layer mixer */ + if (number_of_lms == 4) + zpos = plane >> 1; + + atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "zpos", zpos); + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "FB_ID", + GRSurfaceDrms[current_buffer]->fb_id)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "SRC_X", src_x << 16)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "SRC_Y", src_y << 16)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "SRC_W", src_w << 16)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "SRC_H", src_h << 16)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "CRTC_X", crtc_x)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "CRTC_Y", crtc_y)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "CRTC_W", crtc_w)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "CRTC_H", crtc_h)) + return -EINVAL; + + if (atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[plane].plane->plane_id, "CRTC_ID", + main_monitor_crtc->crtc_id)) + return -EINVAL; + + return 0; +} + +int MinuiBackendDrm::TeardownPipeline(drmModeAtomicReqPtr atomic_req) { + uint32_t i, prop_id; + int ret; + + /* During suspend, tear down pipeline */ + add_prop(&conn_res, connector, Connector, main_monitor_connector->connector_id, "CRTC_ID", 0); + add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "MODE_ID", 0); + add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "ACTIVE", 0); + + for(i = 0; i < number_of_lms; i++) { + ret = atomic_add_prop_to_plane(plane_res, atomic_req, + plane_res[i].plane->plane_id, "CRTC_ID", 0); + if (ret < 0) { + printf("Failed to tear down plane %d\n", i); + return ret; + } + + if (drmModeAtomicAddProperty(atomic_req, plane_res[i].plane->plane_id, fb_prop_id, 0) < 0) { + printf("Failed to add property for plane_id=%d\n", plane_res[i].plane->plane_id); + return -EINVAL; + } + } + + return 0; +} + +int MinuiBackendDrm::SetupPipeline(drmModeAtomicReqPtr atomic_req) { + uint32_t i, prop_id; + int ret; + + for(i = 0; i < number_of_lms; i++) { + add_prop(&conn_res, connector, Connector, main_monitor_connector->connector_id, + "CRTC_ID", main_monitor_crtc->crtc_id); + add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "MODE_ID", crtc_res.mode_blob_id); + add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "ACTIVE", 1); + } + + /* Setup planes */ + for(i = 0; i < number_of_lms; i++) { + ret = AtomicPopulatePlane(i, atomic_req); + if (ret < 0) { + printf("Error populating plane_id = %d\n", plane_res[i].plane->plane_id); + return ret; + } + } + + return 0; +} + GRSurfaceDrm::~GRSurfaceDrm() { if (mmapped_buffer_) { munmap(mmapped_buffer_, row_bytes * height); @@ -138,35 +409,40 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he return surface; } -void MinuiBackendDrm::DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc) { - if (crtc) { - drmModeSetCrtc(drm_fd, crtc->crtc_id, - 0, // fb_id - 0, 0, // x,y - nullptr, // connectors - 0, // connector_count - nullptr); // mode - } +int MinuiBackendDrm::DrmDisableCrtc(drmModeAtomicReqPtr atomic_req) { + return TeardownPipeline(atomic_req); } -bool MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, - const std::unique_ptr<GRSurfaceDrm>& surface) { - if (drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y - &main_monitor_connector->connector_id, - 1, // connector_count - &main_monitor_crtc->mode) != 0) { - perror("Failed to drmModeSetCrtc"); - return false; - } - return true; +int MinuiBackendDrm::DrmEnableCrtc(drmModeAtomicReqPtr atomic_req){ + return SetupPipeline(atomic_req); } void MinuiBackendDrm::Blank(bool blank) { - if (blank) { - DrmDisableCrtc(drm_fd, main_monitor_crtc); - } else { - DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[current_buffer]); + int ret = 0; + + if (blank == current_blank_state) + return; + + drmModeAtomicReqPtr atomic_req = drmModeAtomicAlloc(); + if (!atomic_req) { + printf("Atomic Alloc failed\n"); + return; + } + + if (blank) + ret = DrmDisableCrtc(atomic_req); + else + ret = DrmEnableCrtc(atomic_req); + + if (!ret) + ret = drmModeAtomicCommit(drm_fd, atomic_req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + + if (!ret) { + printf("Atomic Commit failed, rc = %d\n", ret); + current_blank_state = blank; } + + drmModeAtomicFree(atomic_req); } static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources, @@ -272,20 +548,68 @@ drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources } void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) { + uint32_t prop_id; + drmModeAtomicReqPtr atomic_req = drmModeAtomicAlloc(); + for (int i = 0; i < resources->count_connectors; i++) { drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]); drmModeCrtc* crtc = find_crtc_for_connector(fd, resources, connector); if (crtc->crtc_id != main_crtc->crtc_id) { - DrmDisableCrtc(fd, crtc); + // Switching to atomic commit. Given only crtc, we can only set ACTIVE = 0 + // to disable any Nonmain CRTCs + find_prop_id(&crtc_res, crtc, Crtc, crtc->crtc_id, "ACTIVE", prop_id); + if (prop_id == 0) + return; + + if (drmModeAtomicAddProperty(atomic_req, main_monitor_crtc->crtc_id, prop_id, 0) < 0) + return; } drmModeFreeCrtc(crtc); } + + if (!drmModeAtomicCommit(drm_fd, atomic_req,DRM_MODE_ATOMIC_ALLOW_MODESET, NULL)) + printf("Atomic Commit failed in DisableNonMainCrtcs\n"); + + drmModeAtomicFree(atomic_req); +} + +void MinuiBackendDrm::UpdatePlaneFB() { + uint32_t i, prop_id; + + /* Set atomic req */ + drmModeAtomicReqPtr atomic_req = drmModeAtomicAlloc(); + if (!atomic_req) { + printf("Atomic Alloc failed. Could not update fb_id\n"); + return; + } + + /* Add conn-crtc association property required + * for driver to recognize quadpipe topology. + */ + add_prop(&conn_res, connector, Connector, main_monitor_connector->connector_id, + "CRTC_ID", main_monitor_crtc->crtc_id); + + /* Add property */ + for(i = 0; i < number_of_lms; i++) + drmModeAtomicAddProperty(atomic_req, plane_res[i].plane->plane_id, + fb_prop_id, GRSurfaceDrms[current_buffer]->fb_id); + + /* Commit changes */ + int32_t ret; + ret = drmModeAtomicCommit(drm_fd, atomic_req, + DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + + drmModeAtomicFree(atomic_req); + + if (ret) + printf("Atomic commit failed ret=%d\n", ret); } GRSurface* MinuiBackendDrm::Init() { drmModeRes* res = nullptr; drm_fd = -1; + number_of_lms = DEFAULT_NUM_LMS; /* Consider DRM devices in order. */ for (int i = 0; i < DRM_MAX_MINOR; i++) { auto dev_name = android::base::StringPrintf(DRM_DEV_NAME, DRM_DIR_NAME, i); @@ -353,58 +677,111 @@ GRSurface* MinuiBackendDrm::Init() { current_buffer = 0; - // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails. - if (!DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1])) { - return nullptr; + drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1); + + /* Get possible plane_ids */ + drmModePlaneRes *plane_options = drmModeGetPlaneResources(drm_fd); + if (!plane_options || !plane_options->planes || (plane_options->count_planes < number_of_lms)) + return NULL; + + /* Set crtc resources */ + crtc_res.props = drmModeObjectGetProperties(drm_fd, + main_monitor_crtc->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!crtc_res.props) + return NULL; + + crtc_res.props_info = static_cast<drmModePropertyRes **> + (calloc(crtc_res.props->count_props, + sizeof(crtc_res.props_info))); + if (!crtc_res.props_info) + return NULL; + else + for (int j = 0; j < (int)crtc_res.props->count_props; ++j) + crtc_res.props_info[j] = drmModeGetProperty(drm_fd, + crtc_res.props->props[j]); + + /* Set connector resources */ + conn_res.props = drmModeObjectGetProperties(drm_fd, + main_monitor_connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR); + if (!conn_res.props) + return NULL; + + conn_res.props_info = static_cast<drmModePropertyRes **> + (calloc(conn_res.props->count_props, + sizeof(conn_res.props_info))); + if (!conn_res.props_info) + return NULL; + else { + for (int j = 0; j < (int)conn_res.props->count_props; ++j) { + + conn_res.props_info[j] = drmModeGetProperty(drm_fd, + conn_res.props->props[j]); + + /* Get preferred mode information and extract the + * number of layer mixers needed from the topology name. + */ + if (!strcmp(conn_res.props_info[j]->name, "mode_properties")) { + number_of_lms = get_topology_lm_number(drm_fd, conn_res.props->prop_values[j]); + printf("number of lms in topology %d\n", number_of_lms); + } + } } - return GRSurfaceDrms[0].get(); -} + /* Set plane resources */ + for(uint32_t i = 0; i < number_of_lms; ++i) { + plane_res[i].plane = drmModeGetPlane(drm_fd, plane_options->planes[i]); + if (!plane_res[i].plane) + return NULL; + } -static void page_flip_complete(__unused int fd, - __unused unsigned int sequence, - __unused unsigned int tv_sec, - __unused unsigned int tv_usec, - void *user_data) { - *static_cast<bool*>(user_data) = false; -} + for (uint32_t i = 0; i < number_of_lms; ++i) { + struct Plane *obj = &plane_res[i]; + unsigned int j; + obj->props = drmModeObjectGetProperties(drm_fd, obj->plane->plane_id, + DRM_MODE_OBJECT_PLANE); + if (!obj->props) + continue; + obj->props_info = static_cast<drmModePropertyRes **> + (calloc(obj->props->count_props, sizeof(*obj->props_info))); + if (!obj->props_info) + continue; + for (j = 0; j < obj->props->count_props; ++j) + obj->props_info[j] = drmModeGetProperty(drm_fd, obj->props->props[j]); + } -GRSurface* MinuiBackendDrm::Flip() { - bool ongoing_flip = true; - if (drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, GRSurfaceDrms[current_buffer]->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip) != 0) { - perror("Failed to drmModePageFlip"); - return nullptr; + drmModeFreePlaneResources(plane_options); + plane_options = NULL; + + /* Setup pipe and blob_id */ + if (drmModeCreatePropertyBlob(drm_fd, &main_monitor_crtc->mode, sizeof(drmModeModeInfo), + &crtc_res.mode_blob_id)) { + printf("failed to create mode blob\n"); + return NULL; } - while (ongoing_flip) { - struct pollfd fds = { - .fd = drm_fd, - .events = POLLIN - }; + /* Save fb_prop_id*/ + uint32_t prop_id; + prop_id = find_plane_prop_id(plane_res[0].plane->plane_id, "FB_ID", plane_res); + fb_prop_id = prop_id; - if (poll(&fds, 1, -1) == -1 || !(fds.revents & POLLIN)) { - perror("Failed to poll() on drm fd"); - break; - } + Blank(false); - drmEventContext evctx = { - .version = DRM_EVENT_CONTEXT_VERSION, - .page_flip_handler = page_flip_complete - }; + return GRSurfaceDrms[0].get(); +} - if (drmHandleEvent(drm_fd, &evctx) != 0) { - perror("Failed to drmHandleEvent"); - break; - } - } +GRSurface* MinuiBackendDrm::Flip() { + UpdatePlaneFB(); current_buffer = 1 - current_buffer; return GRSurfaceDrms[current_buffer].get(); } MinuiBackendDrm::~MinuiBackendDrm() { - DrmDisableCrtc(drm_fd, main_monitor_crtc); + Blank(true); + drmModeDestroyPropertyBlob(drm_fd, crtc_res.mode_blob_id); drmModeFreeCrtc(main_monitor_crtc); drmModeFreeConnector(main_monitor_connector); close(drm_fd); diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h index 57ba39b8..d0482831 100644 --- a/minui/graphics_drm.h +++ b/minui/graphics_drm.h @@ -26,6 +26,27 @@ #include "graphics.h" #include "minui/minui.h" +#define NUM_MAIN 1 +#define NUM_PLANES 4 +#define DEFAULT_NUM_LMS 2 + +struct Crtc { + drmModeObjectProperties *props; + drmModePropertyRes **props_info; + uint32_t mode_blob_id; +}; + +struct Connector { + drmModeObjectProperties *props; + drmModePropertyRes **props_info; +}; + +struct Plane { + drmModePlane *plane; + drmModeObjectProperties *props; + drmModePropertyRes ** props_info; +}; + class GRSurfaceDrm : public GRSurface { public: ~GRSurfaceDrm() override; @@ -61,14 +82,24 @@ class MinuiBackendDrm : public MinuiBackend { void Blank(bool) override; private: - void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc); - bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface); + int DrmDisableCrtc(drmModeAtomicReqPtr atomic_req); + int DrmEnableCrtc(drmModeAtomicReqPtr atomic_req); void DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc); drmModeConnector* FindMainMonitor(int fd, drmModeRes* resources, uint32_t* mode_index); + int SetupPipeline(drmModeAtomicReqPtr atomic_req); + int TeardownPipeline(drmModeAtomicReqPtr atomic_req); + void UpdatePlaneFB(); + int AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_req); std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2]; int current_buffer{ 0 }; drmModeCrtc* main_monitor_crtc{ nullptr }; drmModeConnector* main_monitor_connector{ nullptr }; int drm_fd{ -1 }; + bool current_blank_state = true; + int fb_prop_id; + struct Crtc crtc_res; + struct Connector conn_res; + struct Plane plane_res[NUM_PLANES]; + uint32_t number_of_lms; }; diff --git a/recovery.cpp b/recovery.cpp index 36924fbd..134a80d7 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -26,6 +26,9 @@ #include <stdlib.h> #include <string.h> #include <sys/types.h> +#include <sys/mount.h> +#include <fs_mgr.h> +#include <time.h> #include <unistd.h> #include <functional> @@ -53,6 +56,7 @@ #include "install/wipe_data.h" #include "install/wipe_device.h" #include "otautil/boot_state.h" +#include "otautil/dirutil.h" #include "otautil/error_code.h" #include "otautil/paths.h" #include "otautil/sysutil.h" @@ -62,13 +66,18 @@ #include "recovery_utils/logging.h" #include "recovery_utils/roots.h" +static constexpr const char* CACHE_LOG_DIR = "/cache/recovery"; static constexpr const char* COMMAND_FILE = "/cache/recovery/command"; static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg"; static constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log"; static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale"; - static constexpr const char* CACHE_ROOT = "/cache"; +#define MMC_0_TYPE_PATH "/sys/block/mmcblk0/device/type" +#define SDCARD_BLK_0_PATH "/dev/block/mmcblk0p1" +#define MMC_1_TYPE_PATH "/sys/block/mmcblk1/device/type" +#define SDCARD_BLK_1_PATH "/dev/block/mmcblk1p1" + static bool save_current_log = false; /* @@ -310,6 +319,75 @@ static void run_graphics_test(RecoveryUI* ui) { ui->ShowText(true); } +// Check whether the mmc type of provided path (/sys/block/mmcblk*/device/type) +// is SD (sdcard) or not. +static int check_mmc_is_sdcard (const char* mmc_type_path) +{ + std::string mmc_type; + + LOG(INFO) << "Checking mmc type for path : " << mmc_type_path; + + if (!android::base::ReadFileToString(mmc_type_path, &mmc_type)) { + LOG(ERROR) << "Failed to read mmc type : " << strerror(errno); + return -1; + } + LOG(INFO) << "MMC type is : " << mmc_type.c_str(); + if (!strncmp(mmc_type.c_str(), "SD", strlen("SD"))) + return 0; + else + return -1; +} + +// Gather mount point and other info from fstab, find the right block +// path where sdcard is mounted, and try mounting it. +static int do_sdcard_mount(RecoveryUI* ui) +{ + int rc = 0; + ui->Print("Update via sdcard. Mounting sdcard\n"); + Volume *v = volume_for_mount_point("/sdcard"); + if (v == nullptr) { + ui->Print("Unknown volume for /sdcard. Check fstab\n"); + goto error; + } + if (strncmp(v->fs_type.c_str(), "vfat", sizeof("vfat"))) { + ui->Print("Unsupported format on the sdcard: %s\n", + v->fs_type.c_str()); + goto error; + } + + if (check_mmc_is_sdcard(MMC_0_TYPE_PATH) == 0) { + LOG(INFO) << "Mounting sdcard on " << SDCARD_BLK_0_PATH; + rc = mount(SDCARD_BLK_0_PATH, + v->mount_point.c_str(), + v->fs_type.c_str(), + v->flags, + v->fs_options.c_str()); + } + else if (check_mmc_is_sdcard(MMC_1_TYPE_PATH) == 0) { + LOG(INFO) << "Mounting sdcard on " << SDCARD_BLK_1_PATH; + rc = mount(SDCARD_BLK_1_PATH, + v->mount_point.c_str(), + v->fs_type.c_str(), + v->flags, + v->fs_options.c_str()); + } + else { + LOG(ERROR) << "Unable to get the block path for sdcard."; + goto error; + } + + if (rc) { + ui->Print("Failed to mount sdcard : %s\n", + strerror(errno)); + goto error; + } + ui->Print("Done mounting sdcard\n"); + return 0; + +error: + return -1; +} + static void WriteUpdateInProgress() { std::string err; if (!update_bootloader_message({ "--reason=update_in_progress" }, &err)) { @@ -630,6 +708,16 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri std::string locale; auto args_to_parse = StringVectorToNullTerminatedArray(args); + InstallResult status = INSTALL_SUCCESS; + + + if (HasCache() && ensure_path_mounted(CACHE_ROOT) == 0) { + //Create /cache/recovery specifically if it is not created + //As in cases where device is booted into recovery directly after + //flashing recovery folder is not created in init + // TODO(b/140199946) Check what to pass for selabel_handle argument. + mkdir_recursively(CACHE_LOG_DIR, 0777, false, nullptr); + } int arg; int option_index; @@ -686,6 +774,10 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } optind = 1; + // next_action indicates the next target to reboot into upon finishing the install. It could be + // overridden to a different reboot target per user request. + Device::BuiltinAction next_action = shutdown_after ? Device::SHUTDOWN : Device::REBOOT; + printf("stage is [%s]\n", device->GetStage().value_or("").c_str()); printf("reason is [%s]\n", device->GetReason().value_or("").c_str()); @@ -715,14 +807,18 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } printf("\n\n"); + if (update_package) { + if (!strncmp("/sdcard", update_package, 7)) { + if(do_sdcard_mount(ui) != 0) { + status = INSTALL_ERROR; + goto error; + } + } + } + property_list(print_property, nullptr); printf("\n"); - InstallResult status = INSTALL_SUCCESS; - // next_action indicates the next target to reboot into upon finishing the install. It could be - // overridden to a different reboot target per user request. - Device::BuiltinAction next_action = shutdown_after ? Device::SHUTDOWN : Device::REBOOT; - if (update_package != nullptr) { // It's not entirely true that we will modify the flash. But we want // to log the update attempt since update_package is non-NULL. @@ -847,6 +943,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri ui->SetBackground(RecoveryUI::NO_COMMAND); } +error: if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { ui->SetBackground(RecoveryUI::ERROR); if (!ui->IsTextVisible()) { diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp index 19484478..52eae384 100644 --- a/recovery_utils/roots.cpp +++ b/recovery_utils/roots.cpp @@ -297,7 +297,8 @@ int setup_install_mounts() { } for (const FstabEntry& entry : fstab) { // We don't want to do anything with "/". - if (entry.mount_point == "/") { + if (entry.mount_point == "/" || entry.mount_point == "/sdcard" || + entry.mount_point == "/data") { continue; } |