Skip to content

Instantly share code, notes, and snippets.

@yousong
Last active April 6, 2017 15:16
Show Gist options
  • Save yousong/b82426242051ce8af4b13de47c16d725 to your computer and use it in GitHub Desktop.
Save yousong/b82426242051ce8af4b13de47c16d725 to your computer and use it in GitHub Desktop.
Patch for compiling meizuosc/m35x kernel with GCC 5

ARM TAGS, a way for bootloader passing info to kernel. See Booting ARM Linux for a good introduction to this.

m35x has a device-specific (possibly vendor-specific) ATAG_BOOTINFO

arch/arm/include/asm/setup.h, contains type declaration for

	#ifdef CONFIG_MACH_M6X
	/* board bootinfo */
	#define ATAG_BOOTINFO   0x5441000A
	
	#include <linux/bootinfo.h>
	
	struct tag_bootinfo {
	                struct bootinfo b;
	};
	#endif

include/linux/bootinfo.h, this file is for meizu devices only.

  • help functions for getting uboot info from bootinfo
  • enum definication for part order

An excerpt

 11 enum {
 12         PART_KERNEL = 0,
 13         PART_RAMDISK,
 14         PART_RECOVERY,
 15         PART_LOGO,
 16         PART_PARAM,
 17         PART_PRIVATE,
 18         PART_BAT_MODEL,
 19         /* recovery private data partition */
 20         PART_REC_PRIV,
 21         PART_RESERVED1,
 22         PART_RESERVED2,
 23         PART_MAX,
 24 };

 33 struct bootinfo {
 34         u32             info_version;                   // 1/2/3/4/..
 35         struct          part_info part[32];             // partition layout, null terminal
 36         char            uboot_version[64];              // uboot string version
 37         char            build_variant[16];              // eng/user/oversea/..
 38         u8              not_signed_check;               // signed check, 0 means check the signature
 39         u8              board_version;                  // defined by ID1-3 GPIO pin
 40 };

PART_PRIVATE has device serial number, public key for signature verification, mac address

  1. m35x kernel will get S/N and mac address at drivers/mmc/card/block.c with meizu_device_info_init() which is defined in arch/arm/mach-exynos/meizu_security.c.
  2. Contents in PART_PRIVATE are organized as blocks (slots) of 1024 bytes
  3. slot0 is for s/n
  4. slot1 is for mac addresses
  5. slot4 is for camera module

There are two public keys in include/linux/rsa_pubkey.h

  • factory_rsa_pk, for data in PART_PRIVATE parts
  • remote_rsa_pk, not sure what's this for

Prerequisites: we can root the device and these partitions are writable.

  • Disassemble u-boot and see how it works

Code for factory test mode will not be built for RECOVERY_KERNEL.

arch/arm/mach-exynos/board-m6x-factory-test.c provides 2 function pointers: mx_is_factory_test_mode, mx_set_factory_test_led

  • There is not default implementation for them
  • It will not cause memory access error because modules depending on them will also not be built for RECOVERY_KERNEL

There are 4 GPIO pins for factory test mode

  • 1 for factory mode in general
  • 1 for bt test mdoe
  • 1 for gps test mode
  • 1 for driving led of the mode

Exynos is the name of another line of SoC products by Samsung, just like S3C, S5P, etc. They may share many IP cores.

Documentation/devicetree/bindings/media/s5p-mfc.txt

Multi Format Codec (MFC) is the IP present in Samsung SoCs which supports high resolution decoding and encoding functionalities. The MFC device driver is a v4l2 driver which can encode/decode video raw/elementary streams and has support for all popular video codecs.

http://linux-exynos.org/wiki/MFC also has some info on this. But what is VDPAU?

Documentation/video4linux/fimc.txt

The FIMC (Fully Interactive Mobile Camera) device available in Samsung SoC Application Processors is an integrated camera host interface, color space converter, image resizer and rotator. It's also capable of capturing data from LCD controller (FIMD) through the SoC internal writeback data path. There are multiple FIMC instances in the SoCs (up to 4), having slightly different capabilities, like pixel alignment constraints, rotator availability, LCD writeback support, etc. The driver is located at drivers/media/platform/exynos4-is directory.

Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt

FIMD (Fully Interactive Mobile Display) is the Display Controller for the Samsung series of SoCs which transfers the image data from a video memory buffer to an external LCD interface.

Documentation/input/event-codes.txt

The input protocol uses a map of types and codes to express input device values to userspace. This document describes the types and codes and how and when they may be used.

arch/arm/mach-exynos/Kconfig

  • ENG_KERNEL, the one in mx3_defconfig
  • DEV_KERNEL
  • USER_KERNEL, the one in official firmware (see strings zImage | grep '3\.4')
  • UNICOM_KERNEL, will set output china unicom logo at fb probe
  • OVERSEAS_KERNEL
  • RECOVERY_KERNEL, drivers for sound, gps, etc. will not be built

The variant info will also be available in bootinfo.build_variant[] passed from bootloader and this part will be available as /proc/uboot_version (see fs/proc/uboot_version.c). The U-Boot version bootinfo.uboot_version[] will be available as /proc/uboot_git_version

init/Kconfig, it will show up in the following place. /proc/version and output of command uname -r

config LOCALVERSION
        string
        #"Local version - append to kernel release"
        default "-eng"  if ENG_KERNEL
        default "-dev" if DEV_KERNEL
        default "-user" if USER_KERNEL
        default "-overseas" if OVERSEAS_KERNEL
        default "-unicom" if UNICOM_KERNEL
        default "-recovery-release" if RELEASE_RECOVERY
        default "-recovery" if RECOVERY_KERNEL

drivers/video/Kconfig

config M6X_LOGO_UNICOM
	depends on UNICOM_KERNEL
	default y
	bool "MEIZU M6X Unicom Logo"

drivers/video/s3c-fb.c, see s3c_fb_copy_logo_fb()

diff --git a/drivers/gpu/pvr/services4/system/exynos5410/sec_dvfs.c b/drivers/gpu/pvr/services4/system/exynos5410/sec_dvfs.c
index e5e108c..a6423f2 100755
--- a/drivers/gpu/pvr/services4/system/exynos5410/sec_dvfs.c
+++ b/drivers/gpu/pvr/services4/system/exynos5410/sec_dvfs.c
@@ -48,7 +48,8 @@
/* #define USING_BOOST_UP_MODE */
/* #define USING_BOOST_DOWN_MODE */
-#define setmask(a, b) (((1 < a) < 24)|b)
+/* NOTE: this was never actually used */
+#define setmask(a, b) (((1 < a) << 24)|b)
#define getclockmask(a) ((a | 0xFF000000) > 24)
#define getlevelmask(a) (a | 0xFFFFFF)
diff --git a/drivers/media/video/exynos/mfc/s5p_mfc.c b/drivers/media/video/exynos/mfc/s5p_mfc.c
index 394a353..679fd3d 100644
--- a/drivers/media/video/exynos/mfc/s5p_mfc.c
+++ b/drivers/media/video/exynos/mfc/s5p_mfc.c
@@ -200,17 +200,6 @@ void mfc_sched_worker(struct work_struct *work)
mfc_err("no mfc device to run\n");
}
-inline int clear_hw_bit(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- int ret = -1;
-
- if (!atomic_read(&dev->watchdog_run))
- ret = test_and_clear_bit(ctx->num, &dev->hw_lock);
-
- return ret;
-}
-
/* Helper functions for interrupt processing */
/* Remove from hw execution round robin */
inline void clear_work_bit(struct s5p_mfc_ctx *ctx)
diff --git a/drivers/media/video/exynos/mfc/s5p_mfc_common.h b/drivers/media/video/exynos/mfc/s5p_mfc_common.h
index 271f176..8b7b41e 100644
--- a/drivers/media/video/exynos/mfc/s5p_mfc_common.h
+++ b/drivers/media/video/exynos/mfc/s5p_mfc_common.h
@@ -760,7 +760,16 @@ struct s5p_mfc_fmt {
};
int get_framerate(struct timeval *to, struct timeval *from);
-inline int clear_hw_bit(struct s5p_mfc_ctx *ctx);
+static inline int clear_hw_bit(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ int ret = -1;
+
+ if (!atomic_read(&dev->watchdog_run))
+ ret = test_and_clear_bit(ctx->num, &dev->hw_lock);
+
+ return ret;
+}
#if defined(CONFIG_EXYNOS_MFC_V5)
#include "regs-mfc-v5.h"
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index e5834aa..9e5022a 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -97,7 +97,7 @@
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
-#include gcc_header(__GNUC__)
+#include gcc_header(4)
#if !defined(__noclone)
#define __noclone /* not needed */

machine_match imei.dat to see if "machine not match"

Enum defs

enum {
    PART_KERNEL = 0,
    PART_RAMDISK,
    PART_RECOVERY,
    PART_LOGO,
    PART_PARAM,
    PART_PRIVATE,
    PART_BAT_MODEL,
    /* recovery private data partition */
    PART_REC_PRIV,
    PART_RESERVED1,
    PART_RESERVED2,
    PART_MAX,
};

Extracted from uboot2

info_version: 1
uboot_version: U-Boot 2012.07-ged6d281 (Apr 11 2014) for M35X-W release
build_variant: user
not_signed_check: 0
board_version: 0
part  0: start_sec:      1263 (     4ef), sec_count:     20480 (    5000)
part  1: start_sec:     21743 (    54ef), sec_count:     20480 (    5000)
part  2: start_sec:     42223 (    a4ef), sec_count:     40960 (    a000)
part  3: start_sec:     83183 (   144ef), sec_count:     40960 (    a000)
part  4: start_sec:    124143 (   1e4ef), sec_count:     40960 (    a000)
part  5: start_sec:         1 (       1), sec_count:       256 (     100)
part  6: start_sec:    165103 (   284ef), sec_count:        16 (      10)
part  7: start_sec:       273 (     111), sec_count:         2 (       2)
part  8: start_sec:    165119 (   284ff), sec_count:     40960 (    a000)
part  9: start_sec:    206079 (   324ff), sec_count:     40960 (    a000)

part  0: byte_offset:    646656 (   9de00), byte_count:  10485760 (  a00000)
part  1: byte_offset:  11132416 (  a9de00), byte_count:  10485760 (  a00000)
part  2: byte_offset:  21618176 ( 149de00), byte_count:  20971520 ( 1400000)
part  3: byte_offset:  42589696 ( 289de00), byte_count:  20971520 ( 1400000)
part  4: byte_offset:  63561216 ( 3c9de00), byte_count:  20971520 ( 1400000)
part  5: byte_offset:       512 (     200), byte_count:    131072 (   20000)
part  6: byte_offset:  84532736 ( 509de00), byte_count:      8192 (    2000)
part  7: byte_offset:    139776 (   22200), byte_count:      1024 (     400)
part  8: byte_offset:  84540928 ( 509fe00), byte_count:  20971520 ( 1400000)
part  9: byte_offset: 105512448 ( 649fe00), byte_count:  20971520 ( 1400000)

Partition names mmcblk0p[0-4] are occupied by /system, /cache, /userdata, /custom respectively. They are described by MSDOS partition table and parsed by block/partitions/check.c:check_partition()

start_sec		sec_count		block_cnt
60000			300000			1/2
360000			100000
560000			17fa000
460000			100000

Partitions described by bootinfo are going to take indexes starting from 5. If they are to be exported, mmcblk0p5 will contain zImage. See drivers/mmc/card/block.c:init_extra_partition() for details.

Line in `updater-script`
block_image_update("/dev/block/mmcblk0p1", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat");
Relevant files
system.new.dat
system.patch.dat
system.transfer.list
Sample `system.transfer.list`
1
206890
erase 2,0,262144
new 34,0,32770,32833,32835,33347,65535,65536,65538,66050,98301,98304,98306,98369,98371,98883,131071,131072,131074,131586,144683,163840,163842,163905,163907,164419,196607,196608,196610,229376,229378,229441,229443,229955,262143
The first `1` is the version of the mechanism, not the version of the firmware
The second line content `206890` is for total number of blocks to be updated
The third line `erase` is for erasing the target device. `2` is for indicating that there are 2 numbers for range specification: block range 0-262144.
The fourth line `new` is for writing content from `system.new.dat` to the target device. `34` is for specififying that there are 17 ranges to be updated. The updater is expected to read `system.new.dat` sequentially and write them to the specified ranges.
Normally one `BLOCK_SIZE` is 4096 bytes
- Convert sparse Android data image to filesystem ext4 image, https://github.com/xpirt/sdat2img
- Android5.0的更新包中system.new.dat文件的解包,http://blog.csdn.net/howellzhu/article/details/41967523
- updater/blockimg.cpp:PerformBlockImageUpdate()

META-INF/com/mx3/android/updater-script

Partition and content

mmcblk0p7		recovery-uboot.img
mmcblk0p6		ramdisk-uboot.img
mmcblk0p5		zImage
mmcblk0boot0	bootloader.img or boot.img
mmcblk0p1		/system
mmcblk0p4		/custom, may delete `/custom/meizu/` if `/custom/simlock.key` does not exist

See drivers/mmc/card/block.c:init_extra_partition() for details.

Part info from bootinfo are added with index 5 as base. That means PART_REC_PRIV will be available as mmcblk0p[5 + PART_KERNEL], i.e. mmcblk0p12

In normal mode, PART_REC_PRIV is the only partition exported in kernel.

Content of /proc/uboot_version, compare and take index0

eng       0
oversea   1
user      2

property_get("ro.meizu.hardware.modem", buf_modem, "wcdma), take index1

wcdma       index0
td-scdma    index0+3

So

eng,wcdma         0
oversea,wcdma     1
user,wcdma        2
eng,td-scdma      3
oversea,td-scdma  4
user,td-scdma     5

This is also cross-confirmed by contents of bootloader.img

@sanek3214
Copy link

Working?

@yousong
Copy link
Author

yousong commented Apr 6, 2017

Working?

Did not try it yet. The MEIZU M351 is still on service as my only smartphone ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment