├── .gitattributes ├── .gitignore ├── .gitmodules ├── .travis.yml ├── README.md ├── bootstrap ├── COPYING ├── README.md ├── acpi.c ├── acpi.h ├── gnvs.c ├── gnvs.h ├── main.c ├── meson.build ├── meson_options.txt ├── protocol │ ├── AcpiTable.h │ └── GlobalNvsArea.h ├── rsci.c └── rsci.h ├── build-esp.sh ├── examples ├── charger-main-os │ └── README.md ├── multi-boot │ └── README.md └── stock-charger │ ├── README.md │ └── charger.conf └── loader ├── entries ├── android.conf ├── charger.conf ├── fastboot.conf └── recovery.conf └── loader.conf /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.sh text eol=lf 3 | 4 | *.c diff=cpp 5 | *.h diff=cpp 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### C ### 2 | # Prerequisites 3 | *.d 4 | 5 | # Object files 6 | *.o 7 | *.ko 8 | *.obj 9 | *.elf 10 | 11 | # Linker output 12 | *.ilk 13 | *.map 14 | *.exp 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | 26 | # Shared objects (inc. Windows DLLs) 27 | *.dll 28 | *.so 29 | *.so.* 30 | *.dylib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex 39 | 40 | # Debug files 41 | *.dSYM/ 42 | *.su 43 | *.idb 44 | *.pdb 45 | 46 | # Kernel Module Compile Results 47 | *.mod* 48 | *.cmd 49 | .tmp_versions/ 50 | modules.order 51 | Module.symvers 52 | Mkfile.old 53 | dkms.conf 54 | 55 | ### CLion ### 56 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 57 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 58 | 59 | *.iml 60 | 61 | ## Directory-based project format: 62 | .idea/ 63 | 64 | # CMake 65 | cmake-build-debug/ 66 | cmake-build-release/ 67 | 68 | ## File-based project format: 69 | *.ipr 70 | *.iws 71 | 72 | ## Plugin-specific files: 73 | 74 | # IntelliJ 75 | out/ 76 | 77 | # mpeltonen/sbt-idea plugin 78 | .idea_modules/ 79 | 80 | # JIRA plugin 81 | atlassian-ide-plugin.xml 82 | 83 | # Crashlytics plugin (for Android Studio and IntelliJ) 84 | com_crashlytics_export_strings.xml 85 | crashlytics.properties 86 | crashlytics-build.properties 87 | fabric.properties 88 | 89 | ### CMake ### 90 | CMakeCache.txt 91 | CMakeFiles 92 | CMakeScripts 93 | Testing 94 | Makefile 95 | cmake_install.cmake 96 | install_manifest.txt 97 | compile_commands.json 98 | CTestTestfile.cmake 99 | 100 | ### Ninja ### 101 | .ninja_deps 102 | .ninja_log 103 | 104 | ### Project ### 105 | CMakeLists.txt 106 | build/ 107 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "systemd-boot"] 2 | path = systemd-boot 3 | url = https://github.com/me176c-dev/systemd-boot-me176c.git 4 | branch = master 5 | [submodule "android-efi"] 6 | path = android-efi 7 | url = https://github.com/me176c-dev/android-efi.git 8 | branch = master 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: c 3 | 4 | addons: 5 | apt: 6 | packages: 7 | - ninja-build 8 | - gnu-efi 9 | - libpng16-dev 10 | 11 | before_install: 12 | - pyenv shell 3.7 13 | - pip3 install --user meson 14 | 15 | install: true 16 | script: ./build-esp.sh 17 | 18 | notifications: 19 | email: false 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # me176c-boot [![Build Status](https://travis-ci.com/me176c-dev/me176c-boot.svg?branch=master)](https://travis-ci.com/me176c-dev/me176c-boot) 2 | me176c-boot is a custom, unlocked bootloader for the ASUS MeMO Pad 7 (ME176C(X)). It consists out of a 3 | [fork of systemd-boot](https://github.com/me176c-dev/systemd-boot-me176c), a simple UEFI boot manager 4 | and [android-efi](https://github.com/me176c-dev/android-efi), a simple bootloader for Android™ boot images. 5 | 6 | ## Features 7 | - Boot into Android, Recovery and Fastboot 8 | - Unlocked bootloader, can boot into custom ROMs 9 | - Completely open-source and custom built for ASUS MeMO Pad (ME176C(X)) 10 | - Flexible configuration to add further boot targets (e.g. Linux dual boot) 11 | 12 | ## Installation 13 | 0. Make sure that you are running Android 5.0 (Lollipop). 14 | 1. Download and unpack `esp.zip` from [the latest release](https://github.com/me176c-dev/me176c-boot/releases). 15 | 2. Make sure you have [Fastboot installed](https://wiki.lineageos.org/adb_fastboot_guide.html). 16 | 3. Boot the tablet into Fastboot mode: On the stock ROM, press `Volume Down` + `Power`, and release the `Power` button 17 | once the backlight turns on. 18 | 4. Connect the tablet to your PC, and verify that it shows up in `fastboot devices`. 19 | 5. Flash the new EFI System Partition (ESP) extracted from the downloaded ZIP: `fastboot flash ESP esp.img` 20 | 6. **Recommended:** Configure the bootloader to [use the stock charger for offline mode charging](/examples/stock-charger) 21 | 22 | ## Usage 23 | By default, the bootloader will boot into the main Android system. 24 | You can recognize the bootloader by the green Android robot that is shown on boot. 25 | 26 | Press `Volume Down` while booting to show the boot menu. Navigate through the menu with the `Volume Down` key. 27 | Press `Volume Up` to select an option. The `Power` button is **not** working inside the boot menu. 28 | 29 | ### Configuration 30 | You can access the (systemd-boot) configuration files from Recovery: 31 | go to `Mount` and select `EFI System Partiton (ESP)`. 32 | Then you can access the ESP using ADB at `/esp`. 33 | 34 | Here are some links with more information how to configure the bootloader: 35 | 36 | - [`systemd-boot` on ArchLinux Wiki](https://wiki.archlinux.org/index.php/Systemd-boot) 37 | - [android-efi README](https://github.com/me176c-dev/android-efi#systemd-boot) 38 | (`android` boot type is supported in me176c-boot) 39 | 40 | #### Booting from other partitions 41 | There is an additional `volume` option in me176c-boot that allows booting from 42 | other partitions on the internal storage, based on their GPT partition UUID. 43 | The partition needs to be formatted as FAT32. 44 | 45 | #### Examples 46 | - [Using the stock charger](/examples/stock-charger) (recommended) 47 | - [Booting into main OS on charger insertion](/examples/charger-main-os) 48 | - [Dual/multi boot](/examples/multi-boot) (e.g. Android and Linux) 49 | 50 | ### Limitations 51 | The "BIOS" of the tablet can boot from the internal storage and USB(-OTG). 52 | It does not seem to be able to boot directly from external SD cards. 53 | However, it is possible to keep most of the system on the external SD card 54 | by placing only the kernel (the boot partition) on the internal storage. 55 | 56 | The EFI System Partition (ESP) is severely limited in its size (only 16 MiB), 57 | which is usually not enough to keep more than one Linux kernel. That's why 58 | me176c-boot supports booting from other partitions on the internal storage. 59 | 60 | #### Setting up an additional ESP partition 61 | There is an unneeded APD (ASUS Product Demo) partition on the tablet, which has 62 | a reasonable amount of storage (~300 MiB) and is therefore ideal as additional 63 | ESP partition. 64 | It contains a few demo product images/media files that are only used for the 65 | "demo mode" on the stock ROM. 66 | 67 | 1. Boot into TWRP recovery and make a backup of the `APD (ASUS Product Demo)` 68 | partition. Store in it a safe place in case you want to restore it. 69 | 2. Wipe the APD partition, and change its file system to FAT32. 70 | 3. Place the EFI application (e.g. Linux) on the APD partition, and use it 71 | in a boot target using the `volume` option: 72 | 73 | ``` 74 | # Partition UUID of the APD partition 75 | volume 80868086-8086-8086-8086-000000000007 76 | ``` 77 | 78 | ### Troubleshooting 79 | In some cases booting may fail or you make a mistake during the installation. In this case, first power off 80 | the tablet by holding the `Power` button until it turns off. 81 | 82 | #### Recovery 83 | Even with the bootloader entirely broken, you can still boot into Fastboot mode using the rescue mode ("DNX mode"). 84 | 85 | 1. Download the [stock ROM (`UL-K013-WW-12.10.1.36-user.zip`)](https://dlcdnets.asus.com/pub/ASUS/EeePAD/ME176C/UL-K013-WW-12.10.1.36-user.zip) 86 | 2. Extract `esp.zip` and `droidboot.img` from the downloaded ZIP. 87 | 3. Extract `EFI/Intel/efilinux.efi` from `esp.zip`. 88 | 4. Press `Volume Up` + `Volume Down` + `Power` until "Fastboot starting..." shows up on the display. 89 | 5. Connect the tablet to your PC, and verify that it shows up in `fastboot devices`. 90 | 6. 91 | ``` 92 | fastboot flash osloader efilinux.efi 93 | fastboot boot droidboot.img 94 | ``` 95 | 96 | ## Building 97 | 1. `git clone --recursive https://github.com/me176c-dev/me176c-boot.git` 98 | 2. `./build-esp.sh` (some commands require root, make sure you can use `sudo`) 99 | 3. `esp.img` and `esp.zip` are in the `build` directory 100 | 101 | ### Project setup 102 | This repository contains 3 separate components: 103 | 104 | - **bootstrap** (`EFI/BOOT/bootx64.efi`): See [bootstrap](bootstrap/README.md). 105 | - **systemd-boot** (`systemd-bootx64.efi`): 106 | A submodule that points to the current version of the [systemd-boot](https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/) fork. 107 | - **android-efi**: (`android.efi`): 108 | The bootloader that boots into Android boot images. 109 | -------------------------------------------------------------------------------- /bootstrap/COPYING: -------------------------------------------------------------------------------- 1 | me176c-bootstrap 2 | Copyright (C) 2018 lambdadroid 3 | 4 | The ACPI/RSCI charger detection is based on code from 5 | kernelflinger (https://github.com/intel/kernelflinger): 6 | Copyright (c) 2013, Intel Corporation 7 | 8 | Additional UEFI protocol headers (protocol/*.h) are taken from 9 | EDK II (https://github.com/tianocore/edk2): 10 | Copyright (c) 2004 - 2018, Intel Corporation 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions are 14 | met: 15 | 16 | 1. Redistributions of source code must retain the above copyright 17 | notice, this list of conditions and the following disclaimer. 18 | 19 | 2. Redistributions in binary form must reproduce the above copyright 20 | notice, this list of conditions and the following disclaimer in the 21 | documentation and/or other materials provided with the distribution. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /bootstrap/README.md: -------------------------------------------------------------------------------- 1 | # me176c-boot bootstrap 2 | bootstrap handles some device-specific initialization for the ASUS MeMO Pad 7 (ME176C/X). 3 | It's a simple EFI application that wraps the primary EFI bootloader. 4 | 5 | ## Features 6 | - **Check if booted due to charger insertion:** In this case, `LoaderEntryOneShot` is set to `charger` to instruct 7 | the primary bootloader to boot into (offline) charging mode. 8 | - **Install ACPI OEM6/GNVS table:** This is required for [me176c-acpi]. 9 | See [Global NVS Area](https://github.com/me176c-dev/me176c-acpi#global-nvs-area). 10 | 11 | ## Build 12 | android-efi is built with [Meson]: 13 | 14 | ``` 15 | meson . build 16 | ninja -C build 17 | ``` 18 | 19 | By default, bootstrap will attempt to load `\systemd-bootx64.efi` as primary bootloader. 20 | To change this, add a `-Dloader=\path\to\bootloader.efi` option when running `meson`. 21 | 22 | ## Usage 23 | Use `build/bootstrap.efi` as primary EFI application: Copy it to `EFI/BOOT/bootx64.efi` on the ESP partition. 24 | Copy your primary bootloader to the path configured above. 25 | 26 | [me176c-acpi]: https://github.com/me176c-dev/me176c-acpi 27 | [Meson]: https://mesonbuild.com/ 28 | -------------------------------------------------------------------------------- /bootstrap/acpi.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2018 lambdadroid 3 | 4 | /* 5 | * Based on: (BSD-2-Clause) 6 | * https://github.com/intel/kernelflinger/blob/f79f4b2f9f8760f191d48b1ff03ec15e75118a90/include/libkernelflinger/acpi.h 7 | * https://github.com/intel/kernelflinger/blob/d8a2c52855a7d8965bd44901dc38bc375d6bcb05/libkernelflinger/acpi.c 8 | * Copyright (c) 2013, Intel Corporation 9 | */ 10 | 11 | #include "acpi.h" 12 | #include 13 | 14 | struct RSDP_TABLE { 15 | struct { 16 | CHAR8 signature[8]; /* "RSD PTR " */ 17 | CHAR8 checksum; /* RSDP Checksum (bytes 0-19) */ 18 | CHAR8 oem_id[6]; /* OEM ID String */ 19 | CHAR8 revision; /* ACPI Revision (0=1.0,2=2.0) */ 20 | UINT32 rsdt_address; /* 32-bit RSDT Pointer */ 21 | } v1; 22 | UINT32 length; /* RSDP Length */ 23 | UINT64 xsdt_address; /* 64-bit XSDT Pointer */ 24 | CHAR8 extended_checksum; /* RSDP Checksum (full) */ 25 | CHAR8 reserved[3]; /* Reserved */ 26 | } __attribute__((packed)); 27 | 28 | #define RSDP_SIGNATURE_SIZE (sizeof(((struct RSDP_TABLE*) 0)->v1.signature)) 29 | static const char RSDP_SIGNATURE[RSDP_SIGNATURE_SIZE] = "RSD PTR "; 30 | 31 | struct XSDT_TABLE { 32 | struct ACPI_TABLE_HEADER header; 33 | UINT64 entry[1]; /* Table Entries */ 34 | } __attribute__((packed)); 35 | 36 | static const char XSDT_SIGNATURE[ACPI_TABLE_SIGNATURE_SIZE] = "XSDT"; 37 | 38 | static CHAR8 acpi_calculate_checksum(const CHAR8 *data, UINT32 len) { 39 | CHAR8 sum = 0; 40 | for (UINT32 i = 0; i < len; ++i) { 41 | sum += data[i]; 42 | } 43 | return sum; 44 | } 45 | 46 | CHAR8 acpi_calculate_table_checksum(const struct ACPI_TABLE_HEADER *table) { 47 | return acpi_calculate_checksum((const CHAR8*) table, table->length); 48 | } 49 | 50 | static inline EFI_STATUS acpi_verify_checksum(const CHAR8 *data, UINT32 len) { 51 | return acpi_calculate_checksum(data, len) == 0 ? EFI_SUCCESS : EFI_CRC_ERROR; 52 | } 53 | 54 | static inline EFI_STATUS acpi_verify_table_checksum(const struct ACPI_TABLE_HEADER *table) { 55 | return acpi_calculate_table_checksum(table) == 0 ? EFI_SUCCESS : EFI_CRC_ERROR; 56 | } 57 | 58 | static EFI_STATUS get_xsdt_table(struct XSDT_TABLE **xsdt) { 59 | EFI_GUID acpi_guid = ACPI_20_TABLE_GUID; 60 | struct RSDP_TABLE *rsdp; 61 | EFI_STATUS ret = LibGetSystemConfigurationTable(&acpi_guid, (VOID**) &rsdp); 62 | if (ret) { 63 | return ret; 64 | } 65 | 66 | if (CompareMem(rsdp->v1.signature, RSDP_SIGNATURE, sizeof(RSDP_SIGNATURE))) { 67 | return EFI_COMPROMISED_DATA; 68 | } 69 | if (rsdp->v1.revision < 2) { 70 | return EFI_UNSUPPORTED; 71 | } 72 | 73 | ret = acpi_verify_checksum((const CHAR8*) rsdp, sizeof(rsdp->v1)); 74 | if (ret) { 75 | return ret; 76 | } 77 | 78 | ret = acpi_verify_checksum((const CHAR8*) rsdp, sizeof(*rsdp)); 79 | if (ret) { 80 | return ret; 81 | } 82 | 83 | *xsdt = (struct XSDT_TABLE *) rsdp->xsdt_address; 84 | if (CompareMem((*xsdt)->header.signature, XSDT_SIGNATURE, sizeof(XSDT_SIGNATURE))) { 85 | return EFI_COMPROMISED_DATA; 86 | } 87 | 88 | ret = acpi_verify_table_checksum(&(*xsdt)->header); 89 | if (ret) { 90 | return ret; 91 | } 92 | 93 | return EFI_SUCCESS; 94 | } 95 | 96 | EFI_STATUS acpi_get_table(struct ACPI_TABLE_HEADER **table, const CHAR8 signature[ACPI_TABLE_SIGNATURE_SIZE]) { 97 | struct XSDT_TABLE *xsdt; 98 | EFI_STATUS ret = get_xsdt_table(&xsdt); 99 | if (ret) { 100 | return ret; 101 | } 102 | 103 | UINTN table_count = (xsdt->header.length - sizeof(xsdt->header)) / sizeof(xsdt->entry[0]); 104 | for (UINTN i = 0; i < table_count; ++i) { 105 | struct ACPI_TABLE_HEADER *header = (struct ACPI_TABLE_HEADER*) xsdt->entry[i]; 106 | if (!CompareMem(header->signature, signature, ACPI_TABLE_SIGNATURE_SIZE)) { 107 | *table = header; 108 | return acpi_verify_table_checksum(header); 109 | } 110 | } 111 | 112 | return EFI_NOT_FOUND; 113 | } 114 | -------------------------------------------------------------------------------- /bootstrap/acpi.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2018 lambdadroid 3 | 4 | #ifndef BOOTSTRAP_ACPI_H 5 | #define BOOTSTRAP_ACPI_H 6 | 7 | /* 8 | * Based on: (BSD-2-Clause) 9 | * https://github.com/intel/kernelflinger/blob/f79f4b2f9f8760f191d48b1ff03ec15e75118a90/include/libkernelflinger/acpi.h 10 | * Copyright (c) 2013, Intel Corporation 11 | */ 12 | 13 | #include 14 | 15 | /** Generic ACPI table header **/ 16 | struct ACPI_TABLE_HEADER { 17 | CHAR8 signature[4]; /* ASCII Table identifier */ 18 | UINT32 length; /* Length of the table, including the header */ 19 | CHAR8 revision; /* Revision of the structure */ 20 | CHAR8 checksum; /* Sum of all fields must be 0 */ 21 | CHAR8 oem_id[6]; /* ASCII OEM identifier */ 22 | CHAR8 oem_table_id[8]; /* ASCII OEM table identifier */ 23 | UINT32 oem_revision; /* OEM supplied revision number */ 24 | CHAR8 creator_id[4]; /* Vendor ID of utility creator of the table */ 25 | UINT32 creator_revision; /* Revision of utility creator of the table */ 26 | } __attribute__((packed)); 27 | 28 | #define ACPI_TABLE_SIGNATURE_SIZE (sizeof(((struct ACPI_TABLE_HEADER*)0)->signature)) 29 | 30 | CHAR8 acpi_calculate_table_checksum(const struct ACPI_TABLE_HEADER *table); 31 | EFI_STATUS acpi_get_table(struct ACPI_TABLE_HEADER **table, const CHAR8 signature[ACPI_TABLE_SIGNATURE_SIZE]); 32 | 33 | #define _acpi_table_has_field(table, member) (((UINTN) &(member) + sizeof(member)) <= (table)->header.length) 34 | #define acpi_table_has_field(table, name) _acpi_table_has_field(table, ((typeof(table)) 0)->name) 35 | 36 | #endif //BOOTSTRAP_ACPI_H 37 | -------------------------------------------------------------------------------- /bootstrap/gnvs.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2019 lambdadroid 3 | 4 | #include 5 | #include 6 | #include "protocol/AcpiTable.h" 7 | #include "protocol/GlobalNvsArea.h" 8 | 9 | #include "acpi.h" 10 | #include "gnvs.h" 11 | 12 | #define AML_NAME_OP 0x08 13 | #define AML_DWORD_OP 0x0c 14 | 15 | static struct { 16 | struct ACPI_TABLE_HEADER header; 17 | UINT8 name_op; 18 | CHAR8 name[4]; 19 | UINT8 data_op; 20 | UINT32 data; 21 | } __attribute__((packed)) gnvs_table = { 22 | .header = { 23 | .signature = "OEM6", 24 | .length = sizeof(gnvs_table), 25 | .revision = 2, 26 | .oem_id = "ME176C", 27 | .oem_table_id = "GNVS", 28 | .creator_id = "BOOT", 29 | }, 30 | .name_op = AML_NAME_OP, 31 | .name = "NVSA", 32 | .data_op = AML_DWORD_OP, 33 | }; 34 | 35 | EFI_GUID gEfiAcpiTableProtocolGuid = EFI_ACPI_TABLE_PROTOCOL_GUID; 36 | #define AcpiTableProtocol gEfiAcpiTableProtocolGuid 37 | 38 | EFI_GUID gEfiGlobalNvsAreaProtocolGuid = EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID; 39 | #define GlobalNvsAreaProtocol gEfiGlobalNvsAreaProtocolGuid 40 | 41 | EFI_STATUS acpi_gnvs_install() { 42 | EFI_GLOBAL_NVS_AREA_PROTOCOL *gnvs_protocol; 43 | EFI_STATUS ret = LibLocateProtocol(&GlobalNvsAreaProtocol, (VOID**) &gnvs_protocol); 44 | if (ret) { 45 | return ret; 46 | } 47 | 48 | // Update ACPI table with proper offset 49 | gnvs_table.data = (UINT32) (UINTN) gnvs_protocol->Area; 50 | 51 | // Calculate checksum 52 | gnvs_table.header.checksum = (CHAR8) -acpi_calculate_table_checksum(&gnvs_table.header); 53 | 54 | EFI_ACPI_TABLE_PROTOCOL *acpi_table_protocol; 55 | ret = LibLocateProtocol(&AcpiTableProtocol, (VOID**) &acpi_table_protocol); 56 | if (ret) { 57 | return ret; 58 | } 59 | 60 | // Install ACPI table 61 | UINTN table_key; 62 | return uefi_call_wrapper(acpi_table_protocol->InstallAcpiTable, 4, acpi_table_protocol, 63 | &gnvs_table, sizeof(gnvs_table), &table_key); 64 | } 65 | -------------------------------------------------------------------------------- /bootstrap/gnvs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2019 lambdadroid 3 | 4 | #ifndef BOOTSTRAP_SSDT_GNVS_H 5 | #define BOOTSTRAP_SSDT_GNVS_H 6 | 7 | #include 8 | 9 | EFI_STATUS acpi_gnvs_install(); 10 | 11 | #endif //BOOTSTRAP_SSDT_GNVS_H 12 | -------------------------------------------------------------------------------- /bootstrap/main.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2018 lambdadroid 3 | 4 | #include 5 | #include 6 | 7 | #include "rsci.h" 8 | #include "gnvs.h" 9 | 10 | #ifndef LOADER_PATH 11 | #define LOADER_PATH L"\\systemd-bootx64.efi" 12 | #endif 13 | 14 | // From gummiboot/systemd-boot 15 | static EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} }; 16 | 17 | #define LOADER_ENTRY_VARIABLE L"LoaderEntryOneShot" 18 | #define ENTRY_CHARGER L"charger" 19 | 20 | EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) { 21 | InitializeLib(image, system_table); 22 | 23 | EFI_LOADED_IMAGE *loaded_image; 24 | EFI_STATUS err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID**) &loaded_image, 25 | image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); 26 | if (err) { 27 | Print(L"Failed to open loaded image protocol\n"); 28 | return err; 29 | } 30 | 31 | UINTN size = 0; 32 | if (uefi_call_wrapper(RT->GetVariable, 5, LOADER_ENTRY_VARIABLE, &loader_guid, NULL, &size, NULL) == EFI_NOT_FOUND) { 33 | // Check if booted by charger insertion 34 | if (rsci_is_charger_mode()) { 35 | err = uefi_call_wrapper(RT->SetVariable, 5, LOADER_ENTRY_VARIABLE, &loader_guid, 36 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 37 | sizeof(ENTRY_CHARGER), ENTRY_CHARGER); 38 | if (err) { 39 | Print(L"Failed to set charger loader entry: %r\n", err); 40 | } 41 | } 42 | } 43 | 44 | // Install ACPI table with global NVS area address 45 | err = acpi_gnvs_install(); 46 | if (err) { 47 | Print(L"Failed to install ACPI GNVS table: %r\n", err); 48 | } 49 | 50 | EFI_DEVICE_PATH *next_image_path = FileDevicePath(loaded_image->DeviceHandle, LOADER_PATH); 51 | if (!next_image_path) { 52 | Print(L"Failed to get device path of '" LOADER_PATH "'\n"); 53 | return EFI_INVALID_PARAMETER; 54 | } 55 | 56 | EFI_HANDLE next_image; 57 | err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image, next_image_path, NULL, 0, &next_image); 58 | FreePool(next_image_path); 59 | if (err) { 60 | Print(L"Failed to load next image from '" LOADER_PATH "'\n"); 61 | goto out; 62 | } 63 | 64 | err = uefi_call_wrapper(BS->StartImage, 3, next_image, 0, NULL); 65 | if (err) { 66 | Print(L"Failed to start image\n"); 67 | goto out; 68 | } 69 | 70 | out: 71 | uefi_call_wrapper(BS->UnloadImage, 1, next_image); 72 | uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL); 73 | return err; 74 | } 75 | -------------------------------------------------------------------------------- /bootstrap/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-2-Clause 2 | # Copyright (C) 2018 lambdadroid 3 | 4 | project('bootstrap', 'c', 5 | version: '0.3.0', 6 | license: 'BSD-2-Clause', 7 | default_options: [ 8 | 'buildtype=debugoptimized', 9 | 'c_std=gnu11', 10 | 'warning_level=3', 11 | 'werror=true' 12 | ] 13 | ) 14 | 15 | arch = host_machine.cpu_family() 16 | 17 | efi_include_dir = '/usr/include/efi' 18 | efi_include = include_directories( 19 | efi_include_dir, join_paths(efi_include_dir, arch), 20 | is_system: true 21 | ) 22 | efi_lds = '/usr/lib/elf_' + arch + '_efi.lds' 23 | efi_crt = '/usr/lib/crt0-efi-' + arch + '.o' 24 | 25 | bootstrap_lib = shared_library('bootstrap', 26 | 'main.c', 27 | 'acpi.c', 28 | 'rsci.c', 29 | 'gnvs.c', 30 | 31 | include_directories: [efi_include], 32 | c_args: [ 33 | '-fshort-wchar', 34 | '-ffreestanding', 35 | '-fno-strict-aliasing', 36 | '-fno-stack-protector', 37 | '-fno-stack-check', 38 | '-maccumulate-outgoing-args', 39 | '-mno-red-zone', 40 | '-mno-mmx', 41 | '-DGNU_EFI_USE_MS_ABI', 42 | '-DLOADER_PATH=L"' + '\\'.join(get_option('loader').split('/')) + '"' 43 | ], 44 | objects: [efi_crt], 45 | link_args: [ 46 | '-T', efi_lds, 47 | '-nostdlib', 48 | '-z', 'nocombreloc', 49 | '-Wl,-Bsymbolic', 50 | '-lefi', '-lgnuefi' 51 | ] 52 | ) 53 | 54 | objcopy = find_program('objcopy') 55 | 56 | custom_target('bootstrap.efi', 57 | output: 'bootstrap.efi', 58 | input: bootstrap_lib, 59 | 60 | command: [objcopy, 61 | '--target=efi-app-' + arch, 62 | '-j', '.text', 63 | '-j', '.sdata', 64 | '-j', '.data', 65 | '-j', '.dynamic', 66 | '-j', '.dynsym', 67 | '-j', '.rel*', 68 | '@INPUT@', '@OUTPUT@' 69 | ], 70 | 71 | install: true, 72 | install_dir: '' 73 | ) 74 | -------------------------------------------------------------------------------- /bootstrap/meson_options.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-2-Clause 2 | # Copyright (C) 2018 lambdadroid 3 | 4 | option('loader', type : 'string', value : '/systemd-bootx64.efi', 5 | description : 'The path to the main bootloader to load (must be escaped for a C string)') 6 | -------------------------------------------------------------------------------- /bootstrap/protocol/AcpiTable.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | The file provides the protocol to install or remove an ACPI 3 | table from a platform. 4 | 5 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
6 | This program and the accompanying materials 7 | are licensed and made available under the terms and conditions of the BSD License 8 | which accompanies this distribution. The full text of the license may be found at 9 | http://opensource.org/licenses/bsd-license.php 10 | 11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 | 14 | @par Revision Reference: 15 | This Protocol was introduced in UEFI Specification 2.3. 16 | 17 | **/ 18 | 19 | #ifndef __ACPI_TABLE_H___ 20 | #define __ACPI_TABLE_H___ 21 | 22 | #define EFI_ACPI_TABLE_PROTOCOL_GUID \ 23 | { 0xffe06bdd, 0x6107, 0x46a6, { 0x7b, 0xb2, 0x5a, 0x9c, 0x7e, 0xc5, 0x27, 0x5c }} 24 | 25 | 26 | typedef struct _EFI_ACPI_TABLE_PROTOCOL EFI_ACPI_TABLE_PROTOCOL; 27 | 28 | /** 29 | 30 | The InstallAcpiTable() function allows a caller to install an 31 | ACPI table. When successful, the table will be linked by the 32 | RSDT/XSDT. AcpiTableBuffer specifies the table to be installed. 33 | InstallAcpiTable() will make a copy of the table and insert the 34 | copy into the RSDT/XSDT. InstallAcpiTable() must insert the new 35 | table at the end of the RSDT/XSDT. To prevent namespace 36 | collision, ACPI tables may be created using UEFI ACPI table 37 | format. If this protocol is used to install a table with a 38 | signature already present in the system, the new table will not 39 | replace the existing table. It is a platform implementation 40 | decision to add a new table with a signature matching an 41 | existing table or disallow duplicate table signatures and 42 | return EFI_ACCESS_DENIED. On successful output, TableKey is 43 | initialized with a unique key. Its value may be used in a 44 | subsequent call to UninstallAcpiTable to remove an ACPI table. 45 | If an EFI application is running at the time of this call, the 46 | relevant EFI_CONFIGURATION_TABLE pointer to the RSDT is no 47 | longer considered valid. 48 | 49 | 50 | @param This A pointer to a EFI_ACPI_TABLE_PROTOCOL. 51 | 52 | @param AcpiTableBuffer A pointer to a buffer containing the 53 | ACPI table to be installed. 54 | 55 | @param AcpiTableBufferSize Specifies the size, in bytes, of 56 | the AcpiTableBuffer buffer. 57 | 58 | 59 | @param TableKey Returns a key to refer to the ACPI table. 60 | 61 | @retval EFI_SUCCESS The table was successfully inserted 62 | 63 | @retval EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, 64 | TableKey is NULL, or 65 | AcpiTableBufferSize and the size 66 | field embedded in the ACPI table 67 | pointed to by AcpiTableBuffer 68 | are not in sync. 69 | 70 | @retval EFI_OUT_OF_RESOURCES Insufficient resources exist to 71 | complete the request. 72 | @retval EFI_ACCESS_DENIED The table signature matches a table already 73 | present in the system and platform policy 74 | does not allow duplicate tables of this type. 75 | 76 | **/ 77 | typedef 78 | EFI_STATUS 79 | (EFIAPI *EFI_ACPI_TABLE_INSTALL_ACPI_TABLE)( 80 | IN EFI_ACPI_TABLE_PROTOCOL *This, 81 | IN VOID *AcpiTableBuffer, 82 | IN UINTN AcpiTableBufferSize, 83 | OUT UINTN *TableKey 84 | ); 85 | 86 | 87 | /** 88 | 89 | The UninstallAcpiTable() function allows a caller to remove an 90 | ACPI table. The routine will remove its reference from the 91 | RSDT/XSDT. A table is referenced by the TableKey parameter 92 | returned from a prior call to InstallAcpiTable(). If an EFI 93 | application is running at the time of this call, the relevant 94 | EFI_CONFIGURATION_TABLE pointer to the RSDT is no longer 95 | considered valid. 96 | 97 | @param This A pointer to a EFI_ACPI_TABLE_PROTOCOL. 98 | 99 | @param TableKey Specifies the table to uninstall. The key was 100 | returned from InstallAcpiTable(). 101 | 102 | @retval EFI_SUCCESS The table was successfully inserted 103 | 104 | @retval EFI_NOT_FOUND TableKey does not refer to a valid key 105 | for a table entry. 106 | 107 | @retval EFI_OUT_OF_RESOURCES Insufficient resources exist to 108 | complete the request. 109 | 110 | **/ 111 | typedef 112 | EFI_STATUS 113 | (EFIAPI *EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE)( 114 | IN EFI_ACPI_TABLE_PROTOCOL *This, 115 | IN UINTN TableKey 116 | ); 117 | 118 | /// 119 | /// The EFI_ACPI_TABLE_PROTOCOL provides the ability for a component 120 | /// to install and uninstall ACPI tables from a platform. 121 | /// 122 | struct _EFI_ACPI_TABLE_PROTOCOL { 123 | EFI_ACPI_TABLE_INSTALL_ACPI_TABLE InstallAcpiTable; 124 | EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE UninstallAcpiTable; 125 | }; 126 | 127 | extern EFI_GUID gEfiAcpiTableProtocolGuid; 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /bootstrap/protocol/GlobalNvsArea.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.
3 | 4 | This program and the accompanying materials are licensed and made available under 5 | the terms and conditions of the BSD License that accompanies this distribution. 6 | The full text of the license may be found at 7 | http://opensource.org/licenses/bsd-license.php. 8 | 9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 | 12 | Module Name: 13 | GlobalNvsArea.h 14 | 15 | Abstract: 16 | Definition of the global NVS area protocol. This protocol 17 | publishes the address and format of a global ACPI NVS buffer used as a communications 18 | buffer between SMM code and ASL code. 19 | The format is derived from the ACPI reference code, version 0.95. 20 | 21 | **/ 22 | 23 | #ifndef _GLOBAL_NVS_AREA_H_ 24 | #define _GLOBAL_NVS_AREA_H_ 25 | 26 | // 27 | // Global NVS Area Protocol GUID 28 | // 29 | #define EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID \ 30 | { 0x74e1e48, 0x8132, 0x47a1, { 0x8c, 0x2c, 0x3f, 0x14, 0xad, 0x9a, 0x66, 0xdc }} 31 | 32 | // 33 | // Extern the GUID for protocol users. 34 | // 35 | extern EFI_GUID gEfiGlobalNvsAreaProtocolGuid; 36 | 37 | // 38 | // Global NVS Area Protocol 39 | // 40 | typedef struct _EFI_GLOBAL_NVS_AREA_PROTOCOL { 41 | VOID *Area; 42 | } EFI_GLOBAL_NVS_AREA_PROTOCOL; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /bootstrap/rsci.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2018 lambdadroid 3 | 4 | /* 5 | * Based on: (BSD-2-Clause) 6 | * https://github.com/intel/kernelflinger/blob/f79f4b2f9f8760f191d48b1ff03ec15e75118a90/include/libkernelflinger/acpi.h 7 | * https://github.com/intel/kernelflinger/blob/4119291fc90db063e5b9047ed36baed7e19afcc4/include/libkernelflinger/power.h 8 | * Copyright (c) 2013, Intel Corporation 9 | */ 10 | 11 | #include "rsci.h" 12 | #include "acpi.h" 13 | 14 | #include 15 | 16 | static const CHAR8 RSCI_SIGNATURE[ACPI_TABLE_SIGNATURE_SIZE] = "RSCI"; 17 | 18 | struct RSCI_TABLE { 19 | struct ACPI_TABLE_HEADER header; 20 | CHAR8 wake_source; /* How system woken up from S4 or S5 */ 21 | CHAR8 reset_source; /* How system was reset */ 22 | CHAR8 reset_type; /* Identify type of reset */ 23 | CHAR8 shutdown_source; /* How system was last shutdown */ 24 | UINT32 indicators; /* Bitmap with additional info */ 25 | } __attribute__((packed)); 26 | 27 | /* Wake sources */ 28 | enum wake_source { 29 | WAKE_NOT_APPLICABLE, 30 | WAKE_BATTERY_INSERTED, 31 | WAKE_USB_CHARGER_INSERTED, 32 | WAKE_ACDC_CHARGER_INSERTED, 33 | WAKE_POWER_BUTTON_PRESSED, 34 | WAKE_RTC_TIMER, 35 | WAKE_BATTERY_REACHED_IA_THRESHOLD, 36 | WAKE_ERROR = -1, 37 | }; 38 | 39 | static enum wake_source rsci_get_wake_source() { 40 | struct RSCI_TABLE *rsci; 41 | EFI_STATUS ret = acpi_get_table((struct ACPI_TABLE_HEADER**) &rsci, RSCI_SIGNATURE); 42 | if (ret) { 43 | Print(L"Failed to get RSCI table: %r\n", ret); 44 | return WAKE_ERROR; 45 | } 46 | 47 | if (!acpi_table_has_field(rsci, wake_source)) { 48 | Print(L"RSCI table does not contain wake source\n"); 49 | return WAKE_ERROR; 50 | } 51 | 52 | return (enum wake_source) rsci->wake_source; 53 | } 54 | 55 | BOOLEAN rsci_is_charger_mode() { 56 | enum wake_source ws = rsci_get_wake_source(); 57 | return ws == WAKE_USB_CHARGER_INSERTED || ws == WAKE_ACDC_CHARGER_INSERTED; 58 | } 59 | -------------------------------------------------------------------------------- /bootstrap/rsci.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-2-Clause 2 | // Copyright (C) 2018 lambdadroid 3 | 4 | #ifndef BOOTSTRAP_RSCI_H 5 | #define BOOTSTRAP_RSCI_H 6 | 7 | #include 8 | 9 | BOOLEAN rsci_is_charger_mode(); 10 | 11 | #endif //BOOTSTRAP_RSCI_H 12 | -------------------------------------------------------------------------------- /build-esp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | PARTITION_SIZE=33 # In MiB 5 | PARTITION_ID=0x6b303133 # k013 6 | PARTITION_LABEL=ESP 7 | 8 | rm -rf build 9 | mkdir build 10 | cd build 11 | 12 | # Build bootstrap 13 | meson ../bootstrap bootstrap 14 | ninja -C bootstrap 15 | 16 | # Build systemd-boot 17 | meson ../systemd-boot systemd-boot 18 | ninja -C systemd-boot 19 | 20 | # Build android-efi 21 | meson ../android-efi android-efi 22 | ninja -C android-efi 23 | 24 | # Create new partition image 25 | dd if=/dev/zero of=esp.img bs=1M count=$PARTITION_SIZE 26 | loop_device=$(sudo losetup --find --show esp.img) 27 | 28 | # Create FAT32 file system 29 | sudo mkfs.fat -F32 -i $PARTITION_ID -n "$PARTITION_LABEL" "$loop_device" 30 | 31 | # Mount file system 32 | mkdir esp 33 | sudo mount "$loop_device" esp 34 | 35 | # Initial bootloader (for charger detection) 36 | sudo mkdir -p esp/EFI/BOOT 37 | sudo cp bootstrap/bootstrap.efi esp/EFI/BOOT/bootx64.efi 38 | 39 | # Boot selection (systemd-boot) 40 | sudo cp systemd-boot/systemd-bootx64.efi esp 41 | 42 | # Android bootloader 43 | sudo cp android-efi/android.efi esp 44 | 45 | # Configuration 46 | sudo cp -r ../loader esp 47 | 48 | # Unmount and destroy loop device 49 | sudo umount "$loop_device" 50 | sudo losetup -d "$loop_device" 51 | 52 | # Copy licenses 53 | mkdir licenses 54 | cp ../bootstrap/COPYING licenses/COPYING.bootstrap 55 | cp ../systemd-boot/LICENSE licenses/COPYING.systemd-boot 56 | cp ../android-efi/COPYING licenses/COPYING.android-efi 57 | 58 | # Create ZIP 59 | zip -9r esp.zip esp.img licenses 60 | -------------------------------------------------------------------------------- /examples/charger-main-os/README.md: -------------------------------------------------------------------------------- 1 | ## Booting into main OS on charger insertion 2 | If you want to disable the separate charging mode on your tablet and always boot into the main OS, 3 | you can simply copy the primary boot configuration, and use it for the charger as well: 4 | 5 | 1. Boot into Recovery, go to `Mount` and select `EFI System Partition (ESP)`. 6 | 2. Connect the tablet to your PC, and verify that it shows up in `adb devices`. 7 | 3. Download the configuration for your primary boot configuration (e.g. `android.conf`): 8 | 9 | ``` 10 | adb pull /esp/loader/entries/android.conf 11 | ``` 12 | 4. Rename it to `charger.conf`. 13 | 5. Open it in a text editor and change the `title` to `Charger`. 14 | 6. Copy it back to your device: 15 | 16 | ``` 17 | adb push charger.conf /esp/loader/entries/charger.conf 18 | ``` 19 | -------------------------------------------------------------------------------- /examples/multi-boot/README.md: -------------------------------------------------------------------------------- 1 | ## Dual/multi boot 2 | It is possible to set up dual/multi boot to have two or more installations on 3 | the tablet at the same time (e.g. Android and Linux). This works by setting up 4 | additional boot targets and making sure that the installations use separate 5 | partitions. 6 | 7 | You almost certainly need to 8 | [set up an additional ESP partition](/README.md#setting-up-an-additional-esp-partition). 9 | Otherwise there will be barely enough space for a single installation. 10 | 11 | ### Internal Storage 12 | The internal storage is partitioned using a standard Android partition layout, 13 | e.g. a `boot`, `recovery`, `system` and `data` partition. Avoid re-partitioning 14 | when possible: there are `reserved` partitions that may be needed for the device 15 | to boot and it won't be easy to return to Android if you change the partition 16 | layout. 17 | 18 | If you don't want Android, you can use the `data` partition as root partition. 19 | Otherwise, if anything, shrink the `data` partition and add new partitions at the end. 20 | This should not prevent Android from booting. 21 | 22 | Use the additional ESP partition (APD) as boot partition. 23 | 24 | ### External Storage (SD card) 25 | As documented in ["Limitations" (README)](/#readme) it is not possible to 26 | boot directly from an external SD card. However, it is possible to place only 27 | the kernel (or boot partition) on the internal storage and have the actual root 28 | file system on an external SD card. 29 | 30 | 31 | 32 | 33 | 45 | 46 |
AdvantagesDisadvantages
34 | 35 | - No need to re-partition the internal storage 36 | - More available storage (can generally use any size, I tested up to 128 GB) 37 | - Multiple installations possible 38 | 39 | 40 | 41 | - Slower (the SD card reader performance is quite limited) 42 | - Still need kernel (or boot partition) on internal storage 43 | 44 |
47 | 48 | - Use a GUID Partition Table (GPT) on the SD card 49 | - Setup at least a root partition for your system 50 | - Use the additional ESP partition (APD) as boot partition 51 | - Multi boot with Android: 52 | - Change the partition type GUID of the root partition 53 | - e.g. `4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709` (Linux x86_64 root) 54 | - The default - Linux filesystem (`0FC63DAF-8483-4772-8E79-3D69D8477DE4`) - 55 | will appear as external storage on Android 56 | - Consider adding a small partition at the beginning of the disk to share 57 | files between Android/Linux 58 | 59 | ### Example setup (Linux) 60 | The notes above are independent should apply to any OS. 61 | This section shows a specific Linux dual boot setup on the external SD card 62 | with Android on the internal storage. 63 | 64 | - Android is installed normally 65 | - Partitioning on external SD card: 66 | - ~8 GiB Linux filesystem partition for file sharing with Android (FAT32/EXT4/F2FS) 67 | - `/` Linux x86_64 root (`4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709`) partition, 68 | EXT4/F2FS (F2FS is much faster) 69 | - `/boot` on APD partition on internal storage, FAT32 70 | - Boot target (`/esp/loader/entries/linux.conf`): 71 | ``` 72 | title Arch Linux 73 | volume 80868086-8086-8086-8086-000000000007 74 | linux /vmlinuz-linux-me176c 75 | initrd /intel-ucode-byt-t-c0.img 76 | initrd /acpi-me176c.img 77 | initrd /initramfs-linux-me176c.img 78 | options root=PARTUUID=... rw 79 | ``` 80 | -------------------------------------------------------------------------------- /examples/stock-charger/README.md: -------------------------------------------------------------------------------- 1 | ## Using the stock charger 2 | You may want to use the stock ROM for (offline) charging since it charges a bit more efficiently (with 3 | less heat being generated). Ideally, this would be fixed directly in the custom ROM, but until then it 4 | is possible to configure the bootloader to use the stock boot image when booting into charging mode: 5 | 6 | 1. Download the [stock ROM (`UL-K013-WW-12.10.1.36-user.zip`)](https://dlcdnets.asus.com/pub/ASUS/EeePAD/ME176C/UL-K013-WW-12.10.1.36-user.zip) 7 | and [the updated charger boot configuration (`charger.conf`)](charger.conf) 8 | 2. Extract `boot.img` from the downloaded ZIP. 9 | 3. Boot into Recovery, go to `Mount` and select `EFI System Partition (ESP)`. 10 | 4. Connect the tablet to your PC, and verify that it shows up in `adb devices`. 11 | 5. 12 | ``` 13 | adb push boot.img /esp/asus-charger.img 14 | adb push charger.conf /esp/loader/entries/charger.conf 15 | ``` 16 | 6. That's it! When you plug in the charger the next time it should boot into the stock charger UI. Yay! 17 | -------------------------------------------------------------------------------- /examples/stock-charger/charger.conf: -------------------------------------------------------------------------------- 1 | title Charger 2 | android /asus-charger.img 3 | options androidboot.mode=charger 4 | -------------------------------------------------------------------------------- /loader/entries/android.conf: -------------------------------------------------------------------------------- 1 | title Android 2 | android 80868086-8086-8086-8086-000000000100 3 | -------------------------------------------------------------------------------- /loader/entries/charger.conf: -------------------------------------------------------------------------------- 1 | title Charger 2 | android 80868086-8086-8086-8086-000000000100 3 | options androidboot.mode=charger 4 | -------------------------------------------------------------------------------- /loader/entries/fastboot.conf: -------------------------------------------------------------------------------- 1 | title Fastboot 2 | android 80868086-8086-8086-8086-000000000102 3 | -------------------------------------------------------------------------------- /loader/entries/recovery.conf: -------------------------------------------------------------------------------- 1 | title Recovery 2 | android 80868086-8086-8086-8086-000000000101 3 | -------------------------------------------------------------------------------- /loader/loader.conf: -------------------------------------------------------------------------------- 1 | default android 2 | auto-entries no 3 | 4 | # Uncomment this to always show the boot menu 5 | #timeout 3 6 | --------------------------------------------------------------------------------