Samsung NX300: Dissecting a Hacked Firmware

I mentioned in an earlier blog post, that I'm working on the Samsung NX300(m) mirrorless cameras and trying to get some features to work. I outlined in that post a way to get unlimited movie record length. While this method seems to screw up the time remaining, recording always stops just over the 4GB file size marker on my NX300m cameras.

Furtunately someone made a hacked formware [1] for the NX300 cameras, which allows unlimted movie record times, and it seems to work fine at least on my NX300. The link [2] leads you to the download for this specific firmware.

In this blog post I'll dive into the differences of the hacked version and an official image of the latest version 1.45 of the firmware for the NX300 camera. This is gonna get technical, so grab your ARM Instruction Set Manual and join me on that journey.

A Tale of two Binary Images

It is hinted in the forum posts, that the firmware for the NX300 and the NX300M are packed differently. I already know, that Samsung shipped different software for the M-models, so I expect I cannot just copy over the hacked NX300 binary to the NX300M. However finding the differences between the original firmware and the one with unlimited video record length may give me a lead to what might be necessary for the same effect on the NX300M.

From the OpenSource-parts of the firmware of the NX300M I already know, that the binary I should be most interested in is the di-camera-app-nx300m or similar, which is the brains of the operation, managing the software modes and configuring the drimeIV ASIC to capture a photo, i.e. read-out the sensor and create an JPEG of that readout on the SD-Card, or capture a movie with sound and encode it as H.264 in mp4-files.

Unpackung and Mounting the Firmware Images

First I need to unpack the nx300.bin firmware images and mount the linux root-filesystem of the camera in my system. I'm using an Arch Linux, so if you want to do the same (or similar thing) on a different distribution, your packages may be called differently.

To unpack the firmware images, I wrote myself a C-program (see below), mmaping the header [3] of the firmware, finding the right offsets and using dd to extract the different parts. See, the firmware image is essentially a header and then cated files behind each other. The header contains the offset and size of each section in the firmware image.

The only file I'm actually interested in, is the platform.img, which contains the whole linux filesystem. The others are some kind of loaders and probably firmware for the drime4 itself. However it is not simply a copy of an ext4-filesystem to be mounted, it is a UBIFS, which is used for flash based filesystems.

Mounting the filesystem is a bit cumbersome, so I've written myself a Makefile. First the nandsim module is loaded, the platform.img is copied into the mtd0 device of the nandsim module, then ubi is loaded and mtd0 is attached to the ubi-driver. Lastly the ubi-device is mounted to /mnt/ubi, which allows us finally to view the goods inside.

mount: platform.img
    echo "run as root"
    modprobe nandsim cache_file=./temp_nand.dat first_id_byte=0x20 second_id_byte=0xac third_id_byte=0x00 fourth_id_byte=0x15
    dd if=platform.img of=/dev/mtd0 bs=2048
    modprobe ubi
    ubiattach -m 0 -O 2048
    -mkdir /mnt/ubi
    mount -t ubifs ubi0_0 /mnt/ubi

You may need the package mtd-utils for mounting the image.

Finding Differences

Now the real problem starts. How to find differences in the image? I already know from the opensource package, that there are loads of libraries and the di-camera-app, which implement most of the cameras functionality. Then maybe there might be some files not present in one or the other.

So i've written myself a small, overengineered bash script md5ing all files and comparing the hashes against each other. The differences show in /etc/version.info with an additional byte, that looks astonishingly like a 'c' after the version number, and in the di-camera-app. The other differing files are due to a bug I didn't bother to fix, as the script does not handle spaces in the file paths well at all.

Dissecting the Disassembly

Ok, we've essentially found out, that the main difference seems to be in the di-camera-app, which is more or less expected, since this binary handles all of the ARM-side software of the camera. So, I've run arm-none-eabi-objdump on them and took a diff (for the lulz I repeated that with forced thumb-mode, which did not go well, so I can be sure, that this code seems to be regular ARM code).

2c2
< di-camera-app-hacked:     file format elf32-littlearm
---
> di-camera-app-original:     file format elf32-littlearm
381052c381052
<   177670: e3e03102    mvn r3, #-2147483648    ; 0x80000000
---
>   177670: e3a03000    mov r3, #0
443109c443109
<   1b3840: e3e03102    mvn r3, #-2147483648    ; 0x80000000
---
>   1b3840: e3003706    movw    r3, #1798   ; 0x706

Aha! Two differences, about 4 changed bytes, that makes all the difference. But why? Well, let's look at the disassembly of the unofficial firmware, especially around where I found the differences:

00177660 <_Z28UI_Get_Storage_File_Max_Sizev@@Base>:
  177660:   e52db004    push    {fp}        ; (str fp, [sp, #-4]!)
  177664:   e28db000    add fp, sp, #0
  177668:   e24dd00c    sub sp, sp, #12
  17766c:   e3e02000    mvn r2, #0
> 177670:   e3e03102    mvn r3, #-2147483648    ; 0x80000000
  177674:   e14b20fc    strd    r2, [fp, #-12]
  177678:   e14b20dc    ldrd    r2, [fp, #-12]
  17767c:   e1a00002    mov r0, r2
  177680:   e1a01003    mov r1, r3
  177684:   e28bd000    add sp, fp, #0
  177688:   e8bd0800    ldmfd   sp!, {fp}
  17768c:   e12fff1e    bx  lr

I've marked the changed line. At first there was an mov r3, #0 which would have set the register r3 to the value of 0, now it's a move negative mvn r3, #0x80000000. This instruction bitwise negates the source operand and sets the destination with the value, i.e. making r3 the largest possible signed 32 bit value 0x7fffffff.

From what I can get, this seems to be intializing one of the two return parameters to the maximal value, so make the calling code think, that the maximal file size of the file system is essentially unlimited. However, the code looks somewhat weird. strd and ldrd are store and load-operations on double-words, so I assume that this code means r2 and r3 are stored onto the newly created stack and read back from it. It looks to me, that the Samsung engineers forgot to enable compiler optimizations, as no normal not-braindead-compiler wouldn't keep these values just in the registers.

A bit concerning is the bx instruction at the end, which is a branch (to the Link Register lr, which is the ARM version of a return), but with changing the instruction set. So whatever it returns to should be Thumb code, if I understand that correctly. Maybe I'll have to do more research on that.

Well, let's get to the second change. I'll abbreviate it here, but I'll put the whole file in the appendix.

001b3584 <_Z25UI_Get_Movie_Remaian_Timev@@Base>:
...
  1b3610:   ebff0fff    bl  177614 <_Z25UI_Get_Storage_Free_Spacev@@Base>
  1b3614:   e1a02000    mov r2, r0
  1b3618:   e1a03001    mov r3, r1
  1b361c:   e14b26fc    strd    r2, [fp, #-108] ; 0xffffff94
> 1b3620:   ebff100e    bl  177660 <_Z28UI_Get_Storage_File_Max_Sizev@@Base>
  1b3624:   e1a02000    mov r2, r0
  1b3628:   e1a03001    mov r3, r1
  1b362c:   e14b27f4    strd    r2, [fp, #-116] ; 0xffffff8c
  1b3630:   e3a02000    mov r2, #0
  1b3634:   e3a03000    mov r3, #0
  1b3638:   e14b22f4    strd    r2, [fp, #-36]  ; 0xffffffdc
  1b363c:   e3a03000    mov r3, #0
  1b3640:   e50b3028    str r3, [fp, #-40]  ; 0xffffffd8
  1b3644:   e3a00053    mov r0, #83 ; 0x53
  1b3648:   ebfed3f2    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b364c:   e1a03000    mov r3, r0
  1b3650:   e50b3078    str r3, [fp, #-120] ; 0xffffff88
  1b3654:   e3a00050    mov r0, #80 ; 0x50
  1b3658:   ebfed3ee    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b365c:   e1a03000    mov r3, r0
  1b3660:   e50b307c    str r3, [fp, #-124] ; 0xffffff84
  1b3664:   e51b007c    ldr r0, [fp, #-124] ; 0xffffff84
  1b3668:   e3a01000    mov r1, #0
  1b366c:   eb001748    bl  1b9394 <_Z22UI_Set_Attr_Movie_Size18eUI_CAP_MOVIE_SIZE@@Base+0x1100>
  1b3670:   e1a03000    mov r3, r0
  1b3674:   e50b3060    str r3, [fp, #-96]  ; 0xffffffa0
  1b3678:   e51b007c    ldr r0, [fp, #-124] ; 0xffffff84
  1b367c:   ebffff3c    bl  1b3374 <_Z21UI_Get_Video_Bit_Rate18eUI_CAP_MOVIE_SIZE@@Base>
  1b3680:   e1a03000    mov r3, r0
  1b3684:   e50b3058    str r3, [fp, #-88]  ; 0xffffffa8
  1b3688:   e24b2084    sub r2, fp, #132    ; 0x84
  1b368c:   e24b3088    sub r3, fp, #136    ; 0x88
  1b3690:   e1a00002    mov r0, r2
  1b3694:   e1a01003    mov r1, r3
  1b3698:   ebffff98    bl  1b3500 <_Z21UI_Get_Audio_Bit_RatePiS_@@Base>
  1b369c:   e51b2068    ldr r2, [fp, #-104] ; 0xffffff98
  1b36a0:   e51b3070    ldr r3, [fp, #-112] ; 0xffffff90
  1b36a4:   e1520003    cmp r2, r3
...
  1b37e8:   ebfadace    bl  6a328 <mm_util_movie_record_time@plt>
  1b37ec:   e1a03000    mov r3, r0
  1b37f0:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b37f4:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b37f8:   e3530000    cmp r3, #0
  1b37fc:   1a000006    bne 1b381c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x298>
  1b3800:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b3804:   e2832003    add r2, r3, #3
  1b3808:   e3530000    cmp r3, #0
  1b380c:   b1a03002    movlt   r3, r2
  1b3810:   e1a03143    asr r3, r3, #2
  1b3814:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b3818:   ea000007    b   1b383c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2b8>
  1b381c:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b3820:   e3530001    cmp r3, #1
  1b3824:   1a000004    bne 1b383c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2b8>
  1b3828:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b382c:   e1a02fa3    lsr r2, r3, #31
  1b3830:   e0823003    add r3, r2, r3
  1b3834:   e1a030c3    asr r3, r3, #1
  1b3838:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b383c:   e51b2018    ldr r2, [fp, #-24]  ; 0xffffffe8
> 1b3840:   e3e03102    mvn r3, #-2147483648    ; 0x80000000
  1b3844:   e1520003    cmp r2, r3
  1b3848:   da000002    ble 1b3858 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2d4>
  1b384c:   e3003707    movw    r3, #1799   ; 0x707
  1b3850:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3854:   ea000001    b   1b3860 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2dc>
  1b3858:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b385c:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3860:   e51b307c    ldr r3, [fp, #-124] ; 0xffffff84
  1b3864:   e3530007    cmp r3, #7
...

This one is a bit bigger. First, we find the only call-site of the StorageMax function we saw our first change in. The return values are stored in r2 and r3 and placed on the stack. I'd assume, that there is a cmp (compare) statement with these values later on, which would stop the recording, when the file size limit is hit.

Then later on, near the middle of the function, but at the end of the excerpt, we find our second change. Normally we'd write the value of 1798 into register r3, but we want to write signed integer max. You know 1798 looks an awful lot like the maximal amount of seconds a video can be. And sure enough, when we divide 60 from it, we get 29.9 minutes, which is the maximal time for 1080p30 videos. In the 1080p60 video mode, the time is reduced to 21 minutes and a few seconds, because the file size exceeds the 4G limit by the FAT-filesystem. However the SD cards are formatted to exfat in the NX300M which allows for nearly unlimited file sized.

One thing to note here is, that there is a function UI::GetVideoBitRate in the function. One can savely assume, that this function may be used for communication with the drime4 ASIC to set the correct bitrate and quality setting for the movie recording. That may of course also be a red hering.

Conclusion

So, from what I can understand, the breaking points on the NX300 were the maximal file size of the filesystem. I did not see where the function would get the information about the file system on the SD card, so this may or may not be breakable by using an ext2-formatted card and a cross compiled ext2-kernel module [4].

The second change was to eliminate the hard limit to 30 minutes of movie recording. I haven't investigated that close enough, but maybe there is a check for the system parameter, where we could disable the recording limit.

References

[1] https://www.dpreview.com/forums/post/56754944
[2] https://mega.nz/file/RAJCiIIZ#LappfCn1QSppxx9eu49DvTqS9GhvSYA_Edqr6S6o2ZA
[3] https://sites.google.com/site/nxcryptophotography/diy-firmware
[4] https://lemmster.de/cross-compile-kernel-module-samsung-nx300-ubnut-14.04.html

Appendix

extractor.c

// CC-BY-NC-SA Stefan Naumann
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>

#include <unistd.h>
#include <assert.h>

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include <string.h>

struct meta {
    uint32_t size;
    uint32_t crc;
    uint32_t start;
    uint32_t unknown; // maybe address for flash?
};

#define PRINT_META(name,x) printf("%s { \n\tsize : 0x%08lx\n\tcrc  : 0x%08lx\n\tstart: 0x%08lx\n\tunknown: %lx\n};\n", name, x.size, x.crc, x.start, x.unknown);

struct header {
    uint8_t stuff[0x40];
    struct meta vimage;
    struct meta d4ipl;
    struct meta d4pnlbl;
    struct meta uimage;
    struct meta platform;
    struct meta pcache;
};

const char* name[] = {
    "vImage",
    "D4_IPL",
    "D4_PNLBL",
    "uImage",
    "platform",
    "pcache"
};

const char* fname[] = {
    "vImage",
    "D4_IPL.bin",
    "D4_PNLBL.bin",
    "uImage",
    "platform.img",
    "pcache.list"
};

static_assert ( sizeof(struct meta) == 4*4 );
static_assert ( sizeof(struct header) == 0xa0 );

bool checkCRC ( const char* filename, uint32_t crc ) {
    // why bother?
}

int ddout ( struct meta* m, const char* inname, const char* filename ) {
    assert ( strlen(filename) < 17 );
    assert ( strlen(inname) < 197 );
    int pid = fork();
    char skip[20]={0}, count[20]={0}, iff[200]={0}, off[20]={0}, bs[20]="bs=1";
    if ( pid < 0 ) {
        return ( errno != 0 ? errno : EINVAL );
    }
    if ( pid == 0 ) {
        int bsi = 0;
        while ( m->size % (1 << bsi) == 0 && bsi < 32 ) {
            bsi++;
        }
        bsi--;

        if (bsi >= 32) {
            bsi = 0;
        }

        snprintf ( skip, 20, "skip=%ld", m->start );
        snprintf ( count, 20, "count=%ld", m->size );
        snprintf ( iff, 200, "if=%s", inname );
        snprintf ( off, 20, "of=%s", filename );
        snprintf ( bs, 20, "bs=%d", 1 );

        printf ( "%s %s %s %s %s %s status=progress\n", "dd", skip, count, iff, off, bs );
        execlp ( "dd", "dd", skip, count, iff, off, bs, "status=progress", NULL );
        exit(EINVAL);
    }
    int rc;
    waitpid ( pid, &rc, 0 );
    return WEXITSTATUS(rc);
}

int main ( int argc, char** argv ) {
    if ( argc != 2 ) {
        printf ( "usage: %s {filename}\n", argv[0] );
        return EINVAL;
    }

    errno = 0;
    int fd = open ( argv[1], O_RDONLY );
    if ( fd < 0 ) {
        printf ("open: %s\n", strerror ( errno ) );
        return errno;
    }

    struct header* hdr = (struct header*) mmap ( NULL, 0xa0, PROT_READ, MAP_PRIVATE, fd, 0 );
    close ( fd );
    if ( (void*)hdr == (void*)MAP_FAILED ) {
        printf ("mmap: %s\n", strerror ( errno ) );
        return errno;
    }

    struct meta* m = &hdr->vimage;
    for ( int i = 0; i<6; i++ ) {
        PRINT_META ( name[i], m[i] );
        ddout ( &m[i], argv[1], fname[i] );
    }

    munmap ( hdr, 0xa0 );

    return 0;
}

diff.sh

#!/bin/bash
# CC-BY-SA-NC by Stefan Naumann

NORMAL=32
WARN=31
CHECK=34

## "simple" logging function using asci escape colors and output files
function log () {
    level=${2:-${NORMAL}}
    output=${3:-"/dev/stdout"}
    echo -e "\033[${level};1m> $1\033[0m" >> $output
}

log "Usage: diff.sh <orig> <hacked> <outfile>"
log "Tool to find diffrences in two folders, comparing all files"

h=${2:-"hacked"}
o=${1:-"original"}
outfile={3:-"diffout"}

## Use find and md5sum to get all the files, scan their contents 
log "Scanning directory $h"
hmd5=$(find $h -type f -exec md5sum {} + | sort -k 2)
log "Scanning directory $o"
omd5=$(find $o -type f -exec md5sum {} + | sort -k 2)

## vars for progress output
totallines=$(echo "$hmd5" | wc | awk '{print $1}')
i=0
last=0

log "Diffing ($totallines files)"
## for all files
while IFS= read -r line; do
    ## remove prefix from the hacked filename
    hfile=$(echo "$line" | awk '{print $2}')
    hfile=${hfile#"$h"}
    ## find the corresponding file in the original filesystem
    oline=$(echo "$omd5" | grep "${hfile}")

    nlines=$(echo "$oline" | wc | awk '{print $1}')
    stat=0
    ## grep may have found 0, 1 (perfect!) or more equivalents (as I can't search for exact matches)
    if [ $nlines -eq 0 ]; then
        log "Could not find file $hfile" WARN
        continue
    elif [ $nlines -gt 1 ]; then 
        ## if it found >1 equivalent, we have to search ourselves
        while IFS= read -r l2; do
            f=$(echo "$l2" | awk '{print $2}')
            f=${f#"$o"}
            if [ "$f" = "$hfile" ]; then
                oline="$l2"
                stat=1
                break;
            fi
        done <<< "$oline"
    else
        ## exactly one -> perfect
        stat=1
    fi

    ## oline="" if grep did not find anything
    ## stat=0 if grep did not find anything or it found >1 file and we did not
    ## find anything ourselves
    if [ "$oline" = "" ] || [ $stat -eq 0 ]; then 
        log "Did not find file $hfile" WARN
    else
        hsum=$(echo "$line" | awk '{print $1}')
        osum=$(echo "$oline" | awk '{print $1}')
        # check the checksum of the original and hacked file
        if [ "$osum" = "$hsum" ]; then
            :
        else
            log "Checksums did not check out on '$hfile'" $CHECK $outfile
        fi
    fi

    ## progress output
    i=$((i+1))
    next=$((last+250))
    if [ $i -gt $next ]; then
        log "progress ($i/$totallines files)"
        last=$next;
    fi
done <<< "$hmd5"

UI::GetMovieRemaianTime

001b3584 <_Z25UI_Get_Movie_Remaian_Timev@@Base>:
  1b3584:   e92d48f0    push    {r4, r5, r6, r7, fp, lr}
  1b3588:   e28db014    add fp, sp, #20
  1b358c:   e24dd088    sub sp, sp, #136    ; 0x88
  1b3590:   e3a03b01    mov r3, #1024   ; 0x400
  1b3594:   e50b3030    str r3, [fp, #-48]  ; 0xffffffd0
  1b3598:   e3003707    movw    r3, #1799   ; 0x707
  1b359c:   e50b3034    str r3, [fp, #-52]  ; 0xffffffcc
  1b35a0:   e3a0301e    mov r3, #30
  1b35a4:   e50b3038    str r3, [fp, #-56]  ; 0xffffffc8
  1b35a8:   e3a03096    mov r3, #150    ; 0x96
  1b35ac:   e50b303c    str r3, [fp, #-60]  ; 0xffffffc4
  1b35b0:   e3a03f4b    mov r3, #300    ; 0x12c
  1b35b4:   e50b3040    str r3, [fp, #-64]  ; 0xffffffc0
  1b35b8:   e3a03f96    mov r3, #600    ; 0x258
  1b35bc:   e50b3044    str r3, [fp, #-68]  ; 0xffffffbc
  1b35c0:   e3a0300f    mov r3, #15
  1b35c4:   e50b3048    str r3, [fp, #-72]  ; 0xffffffb8
  1b35c8:   e3a03007    mov r3, #7
  1b35cc:   e50b304c    str r3, [fp, #-76]  ; 0xffffffb4
  1b35d0:   e3e03102    mvn r3, #-2147483648    ; 0x80000000
  1b35d4:   e50b3050    str r3, [fp, #-80]  ; 0xffffffb0
  1b35d8:   e3a03000    mov r3, #0
  1b35dc:   e50b3080    str r3, [fp, #-128] ; 0xffffff80
  1b35e0:   e3a03000    mov r3, #0
  1b35e4:   e50b3054    str r3, [fp, #-84]  ; 0xffffffac
  1b35e8:   e3a03000    mov r3, #0
  1b35ec:   e50b3058    str r3, [fp, #-88]  ; 0xffffffa8
  1b35f0:   e3a03000    mov r3, #0
  1b35f4:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b35f8:   e3a03000    mov r3, #0
  1b35fc:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3600:   e3a03000    mov r3, #0
  1b3604:   e50b305c    str r3, [fp, #-92]  ; 0xffffffa4
  1b3608:   e3a03000    mov r3, #0
  1b360c:   e50b3060    str r3, [fp, #-96]  ; 0xffffffa0
  1b3610:   ebff0fff    bl  177614 <_Z25UI_Get_Storage_Free_Spacev@@Base>
  1b3614:   e1a02000    mov r2, r0
  1b3618:   e1a03001    mov r3, r1
  1b361c:   e14b26fc    strd    r2, [fp, #-108] ; 0xffffff94
> 1b3620:   ebff100e    bl  177660 <_Z28UI_Get_Storage_File_Max_Sizev@@Base>
  1b3624:   e1a02000    mov r2, r0
  1b3628:   e1a03001    mov r3, r1
  1b362c:   e14b27f4    strd    r2, [fp, #-116] ; 0xffffff8c
  1b3630:   e3a02000    mov r2, #0
  1b3634:   e3a03000    mov r3, #0
  1b3638:   e14b22f4    strd    r2, [fp, #-36]  ; 0xffffffdc
  1b363c:   e3a03000    mov r3, #0
  1b3640:   e50b3028    str r3, [fp, #-40]  ; 0xffffffd8
  1b3644:   e3a00053    mov r0, #83 ; 0x53
  1b3648:   ebfed3f2    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b364c:   e1a03000    mov r3, r0
  1b3650:   e50b3078    str r3, [fp, #-120] ; 0xffffff88
  1b3654:   e3a00050    mov r0, #80 ; 0x50
  1b3658:   ebfed3ee    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b365c:   e1a03000    mov r3, r0
  1b3660:   e50b307c    str r3, [fp, #-124] ; 0xffffff84
  1b3664:   e51b007c    ldr r0, [fp, #-124] ; 0xffffff84
  1b3668:   e3a01000    mov r1, #0
  1b366c:   eb001748    bl  1b9394 <_Z22UI_Set_Attr_Movie_Size18eUI_CAP_MOVIE_SIZE@@Base+0x1100>
  1b3670:   e1a03000    mov r3, r0
  1b3674:   e50b3060    str r3, [fp, #-96]  ; 0xffffffa0
  1b3678:   e51b007c    ldr r0, [fp, #-124] ; 0xffffff84
  1b367c:   ebffff3c    bl  1b3374 <_Z21UI_Get_Video_Bit_Rate18eUI_CAP_MOVIE_SIZE@@Base>
  1b3680:   e1a03000    mov r3, r0
  1b3684:   e50b3058    str r3, [fp, #-88]  ; 0xffffffa8
  1b3688:   e24b2084    sub r2, fp, #132    ; 0x84
  1b368c:   e24b3088    sub r3, fp, #136    ; 0x88
  1b3690:   e1a00002    mov r0, r2
  1b3694:   e1a01003    mov r1, r3
  1b3698:   ebffff98    bl  1b3500 <_Z21UI_Get_Audio_Bit_RatePiS_@@Base>
  1b369c:   e51b2068    ldr r2, [fp, #-104] ; 0xffffff98
  1b36a0:   e51b3070    ldr r3, [fp, #-112] ; 0xffffff90
  1b36a4:   e1520003    cmp r2, r3
  1b36a8:   8a00000b    bhi 1b36dc <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x158>
  1b36ac:   e51b2068    ldr r2, [fp, #-104] ; 0xffffff98
  1b36b0:   e51b3070    ldr r3, [fp, #-112] ; 0xffffff90
  1b36b4:   e1520003    cmp r2, r3
  1b36b8:   1a000011    bne 1b3704 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x180>
  1b36bc:   e51b206c    ldr r2, [fp, #-108] ; 0xffffff94
  1b36c0:   e51b3074    ldr r3, [fp, #-116] ; 0xffffff8c
  1b36c4:   e1520003    cmp r2, r3
  1b36c8:   8a000003    bhi 1b36dc <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x158>
  1b36cc:   e51b206c    ldr r2, [fp, #-108] ; 0xffffff94
  1b36d0:   e51b3074    ldr r3, [fp, #-116] ; 0xffffff8c
  1b36d4:   e1520003    cmp r2, r3
  1b36d8:   ea000009    b   1b3704 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x180>
  1b36dc:   e14b27d4    ldrd    r2, [fp, #-116] ; 0xffffff8c
  1b36e0:   e14b22f4    strd    r2, [fp, #-36]  ; 0xffffffdc
  1b36e4:   e14b27d4    ldrd    r2, [fp, #-116] ; 0xffffff8c
  1b36e8:   e1a01b03    lsl r1, r3, #22
  1b36ec:   e1a06522    lsr r6, r2, #10
  1b36f0:   e1816006    orr r6, r1, r6
  1b36f4:   e1a07523    lsr r7, r3, #10
  1b36f8:   e1a03006    mov r3, r6
  1b36fc:   e50b3028    str r3, [fp, #-40]  ; 0xffffffd8
  1b3700:   ea000008    b   1b3728 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x1a4>
  1b3704:   e14b26dc    ldrd    r2, [fp, #-108] ; 0xffffff94
  1b3708:   e14b22f4    strd    r2, [fp, #-36]  ; 0xffffffdc
  1b370c:   e14b26dc    ldrd    r2, [fp, #-108] ; 0xffffff94
  1b3710:   e1a01b03    lsl r1, r3, #22
  1b3714:   e1a04522    lsr r4, r2, #10
  1b3718:   e1814004    orr r4, r1, r4
  1b371c:   e1a05523    lsr r5, r3, #10
  1b3720:   e1a03004    mov r3, r4
  1b3724:   e50b3028    str r3, [fp, #-40]  ; 0xffffffd8
  1b3728:   e3a03000    mov r3, #0
  1b372c:   e50b302c    str r3, [fp, #-44]  ; 0xffffffd4
  1b3730:   e3a00030    mov r0, #48 ; 0x30
  1b3734:   eb012277    bl  1fc118 <_Z12UI_Get_State14eUI_STATE_ITEM@@Base>
  1b3738:   e1a03000    mov r3, r0
  1b373c:   e3530001    cmp r3, #1
  1b3740:   13a03000    movne   r3, #0
  1b3744:   03a03001    moveq   r3, #1
  1b3748:   e6ef3073    uxtb    r3, r3
  1b374c:   e3530000    cmp r3, #0
  1b3750:   0a00000d    beq 1b378c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x208>
  1b3754:   e3a000c3    mov r0, #195    ; 0xc3
  1b3758:   ebfed3ae    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b375c:   e1a03000    mov r3, r0
  1b3760:   e3530001    cmp r3, #1
  1b3764:   13a03000    movne   r3, #0
  1b3768:   03a03001    moveq   r3, #1
  1b376c:   e6ef3073    uxtb    r3, r3
  1b3770:   e3530000    cmp r3, #0
  1b3774:   0a000002    beq 1b3784 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x200>
  1b3778:   e3a03004    mov r3, #4
  1b377c:   e50b302c    str r3, [fp, #-44]  ; 0xffffffd4
  1b3780:   ea000001    b   1b378c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x208>
  1b3784:   e3a03001    mov r3, #1
  1b3788:   e50b302c    str r3, [fp, #-44]  ; 0xffffffd4
  1b378c:   e14b26dc    ldrd    r2, [fp, #-108] ; 0xffffff94
  1b3790:   e51bc088    ldr ip, [fp, #-136] ; 0xffffff78
  1b3794:   e51b1060    ldr r1, [fp, #-96]  ; 0xffffffa0
  1b3798:   e58d1000    str r1, [sp]
  1b379c:   e51b102c    ldr r1, [fp, #-44]  ; 0xffffffd4
  1b37a0:   e58d1004    str r1, [sp, #4]
  1b37a4:   e1a00002    mov r0, r2
  1b37a8:   e1a01003    mov r1, r3
  1b37ac:   e51b2058    ldr r2, [fp, #-88]  ; 0xffffffa8
  1b37b0:   e1a0300c    mov r3, ip
  1b37b4:   ebfadadb    bl  6a328 <mm_util_movie_record_time@plt>
  1b37b8:   e1a03000    mov r3, r0
  1b37bc:   e50b305c    str r3, [fp, #-92]  ; 0xffffffa4
  1b37c0:   e14b22d4    ldrd    r2, [fp, #-36]  ; 0xffffffdc
  1b37c4:   e51bc088    ldr ip, [fp, #-136] ; 0xffffff78
  1b37c8:   e51b1060    ldr r1, [fp, #-96]  ; 0xffffffa0
  1b37cc:   e58d1000    str r1, [sp]
  1b37d0:   e51b102c    ldr r1, [fp, #-44]  ; 0xffffffd4
  1b37d4:   e58d1004    str r1, [sp, #4]
  1b37d8:   e1a00002    mov r0, r2
  1b37dc:   e1a01003    mov r1, r3
  1b37e0:   e51b2058    ldr r2, [fp, #-88]  ; 0xffffffa8
  1b37e4:   e1a0300c    mov r3, ip
  1b37e8:   ebfadace    bl  6a328 <mm_util_movie_record_time@plt>
  1b37ec:   e1a03000    mov r3, r0
  1b37f0:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b37f4:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b37f8:   e3530000    cmp r3, #0
  1b37fc:   1a000006    bne 1b381c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x298>
  1b3800:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b3804:   e2832003    add r2, r3, #3
  1b3808:   e3530000    cmp r3, #0
  1b380c:   b1a03002    movlt   r3, r2
  1b3810:   e1a03143    asr r3, r3, #2
  1b3814:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b3818:   ea000007    b   1b383c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2b8>
  1b381c:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b3820:   e3530001    cmp r3, #1
  1b3824:   1a000004    bne 1b383c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2b8>
  1b3828:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b382c:   e1a02fa3    lsr r2, r3, #31
  1b3830:   e0823003    add r3, r2, r3
  1b3834:   e1a030c3    asr r3, r3, #1
  1b3838:   e50b3018    str r3, [fp, #-24]  ; 0xffffffe8
  1b383c:   e51b2018    ldr r2, [fp, #-24]  ; 0xffffffe8
> 1b3840:   e3e03102    mvn r3, #-2147483648    ; 0x80000000
  1b3844:   e1520003    cmp r2, r3
  1b3848:   da000002    ble 1b3858 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2d4>
  1b384c:   e3003707    movw    r3, #1799   ; 0x707
  1b3850:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3854:   ea000001    b   1b3860 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x2dc>
  1b3858:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b385c:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3860:   e51b307c    ldr r3, [fp, #-124] ; 0xffffff84
  1b3864:   e3530007    cmp r3, #7
  1b3868:   1a000039    bne 1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b386c:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b3870:   e3530003    cmp r3, #3
  1b3874:   1a000005    bne 1b3890 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x30c>
  1b3878:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b387c:   e3530095    cmp r3, #149    ; 0x95
  1b3880:   da000002    ble 1b3890 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x30c>
  1b3884:   e3a03096    mov r3, #150    ; 0x96
  1b3888:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b388c:   ea000030    b   1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b3890:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b3894:   e3530004    cmp r3, #4
  1b3898:   1a000006    bne 1b38b8 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x334>
  1b389c:   e51b2018    ldr r2, [fp, #-24]  ; 0xffffffe8
  1b38a0:   e300312b    movw    r3, #299    ; 0x12b
  1b38a4:   e1520003    cmp r2, r3
  1b38a8:   da000002    ble 1b38b8 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x334>
  1b38ac:   e3a03f4b    mov r3, #300    ; 0x12c
  1b38b0:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b38b4:   ea000026    b   1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b38b8:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b38bc:   e3530005    cmp r3, #5
  1b38c0:   1a000006    bne 1b38e0 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x35c>
  1b38c4:   e51b2018    ldr r2, [fp, #-24]  ; 0xffffffe8
  1b38c8:   e3003257    movw    r3, #599    ; 0x257
  1b38cc:   e1520003    cmp r2, r3
  1b38d0:   da000002    ble 1b38e0 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x35c>
  1b38d4:   e3a03f96    mov r3, #600    ; 0x258
  1b38d8:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b38dc:   ea00001c    b   1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b38e0:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b38e4:   e3530000    cmp r3, #0
  1b38e8:   1a000005    bne 1b3904 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x380>
  1b38ec:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b38f0:   e3530006    cmp r3, #6
  1b38f4:   da000002    ble 1b3904 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x380>
  1b38f8:   e3a03007    mov r3, #7
  1b38fc:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3900:   ea000013    b   1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b3904:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b3908:   e3530001    cmp r3, #1
  1b390c:   1a000005    bne 1b3928 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3a4>
  1b3910:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b3914:   e353000e    cmp r3, #14
  1b3918:   da000002    ble 1b3928 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3a4>
  1b391c:   e3a0300f    mov r3, #15
  1b3920:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3924:   ea00000a    b   1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b3928:   e51b3078    ldr r3, [fp, #-120] ; 0xffffff88
  1b392c:   e3530002    cmp r3, #2
  1b3930:   1a000005    bne 1b394c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3c8>
  1b3934:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b3938:   e353001d    cmp r3, #29
  1b393c:   da000002    ble 1b394c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3c8>
  1b3940:   e3a0301e    mov r3, #30
  1b3944:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3948:   ea000001    b   1b3954 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3d0>
  1b394c:   e51b3018    ldr r3, [fp, #-24]  ; 0xffffffe8
  1b3950:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3954:   e3000583    movw    r0, #1411   ; 0x583
  1b3958:   ebfed32e    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b395c:   e1a03000    mov r3, r0
  1b3960:   e3530000    cmp r3, #0
  1b3964:   1a000004    bne 1b397c <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x3f8>
  1b3968:   e3a00e3f    mov r0, #1008   ; 0x3f0
  1b396c:   ebfed329    bl  168618 <_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base>
  1b3970:   e1a03000    mov r3, r0
  1b3974:   e353001f    cmp r3, #31
  1b3978:   1a000001    bne 1b3984 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x400>
  1b397c:   e3a03001    mov r3, #1
  1b3980:   ea000000    b   1b3988 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x404>
  1b3984:   e3a03000    mov r3, #0
  1b3988:   e3530000    cmp r3, #0
  1b398c:   0a000001    beq 1b3998 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x414>
  1b3990:   e3e03102    mvn r3, #-2147483648    ; 0x80000000
  1b3994:   e50b301c    str r3, [fp, #-28]  ; 0xffffffe4
  1b3998:   e3a0007c    mov r0, #124    ; 0x7c
  1b399c:   e51b101c    ldr r1, [fp, #-28]  ; 0xffffffe4
  1b39a0:   ebfed36c    bl  168758 <_Z12UI_Set_Value14eUI_VALUE_ITEMi@@Base>
  1b39a4:   e3003048    movw    r3, #72 ; 0x48
  1b39a8:   e340304e    movt    r3, #78 ; 0x4e
  1b39ac:   e5931000    ldr r1, [r3]
  1b39b0:   e24b2080    sub r2, fp, #128    ; 0x80
  1b39b4:   e30a3790    movw    r3, #42896  ; 0xa790
  1b39b8:   e3403026    movt    r3, #38 ; 0x26
  1b39bc:   e58d3000    str r3, [sp]
  1b39c0:   e51b301c    ldr r3, [fp, #-28]  ; 0xffffffe4
  1b39c4:   e58d3004    str r3, [sp, #4]
  1b39c8:   e3a03000    mov r3, #0
  1b39cc:   e58d3008    str r3, [sp, #8]
  1b39d0:   e1a00001    mov r0, r1
  1b39d4:   e1a01002    mov r1, r2
  1b39d8:   e30a2780    movw    r2, #42880  ; 0xa780
  1b39dc:   e3402026    movt    r2, #38 ; 0x26
  1b39e0:   e51b3028    ldr r3, [fp, #-40]  ; 0xffffffd8
  1b39e4:   ebfadf8c    bl  6b81c <mm_camcorder_set_attributes@plt>
  1b39e8:   e1a03000    mov r3, r0
  1b39ec:   e50b3054    str r3, [fp, #-84]  ; 0xffffffac
  1b39f0:   e51b3054    ldr r3, [fp, #-84]  ; 0xffffffac
  1b39f4:   e3530000    cmp r3, #0
  1b39f8:   0a000012    beq 1b3a48 <_Z25UI_Get_Movie_Remaian_Timev@@Base+0x4c4>
  1b39fc:   e51b2080    ldr r2, [fp, #-128] ; 0xffffff80
  1b3a00:   e30a37a4    movw    r3, #42916  ; 0xa7a4
  1b3a04:   e3403026    movt    r3, #38 ; 0x26
  1b3a08:   e58d3000    str r3, [sp]
  1b3a0c:   e51b3054    ldr r3, [fp, #-84]  ; 0xffffffac
  1b3a10:   e58d3004    str r3, [sp, #4]
  1b3a14:   e58d2008    str r2, [sp, #8]
  1b3a18:   e30a0760    movw    r0, #42848  ; 0xa760
  1b3a1c:   e3400026    movt    r0, #38 ; 0x26
  1b3a20:   e30b1744    movw    r1, #46916  ; 0xb744
  1b3a24:   e3401026    movt    r1, #38 ; 0x26
  1b3a28:   e3002251    movw    r2, #593    ; 0x251
  1b3a2c:   e3a03000    mov r3, #0
  1b3a30:   ebfae4ad    bl  6ccec <slpcam_print_log@plt>
  1b3a34:   e51b3080    ldr r3, [fp, #-128] ; 0xffffff80
  1b3a38:   e1a00003    mov r0, r3
  1b3a3c:   ebfade50    bl  6b384 <free@plt>
  1b3a40:   e3a03000    mov r3, #0
  1b3a44:   e50b3080    str r3, [fp, #-128] ; 0xffffff80
  1b3a48:   e51b305c    ldr r3, [fp, #-92]  ; 0xffffffa4
  1b3a4c:   e1a00003    mov r0, r3
  1b3a50:   e24bd014    sub sp, fp, #20
  1b3a54:   e8bd88f0    pop {r4, r5, r6, r7, fp, pc}

Last edit: 13.06.2021 00:30