Hello, i want to edit some files in a recovery.img file but i cant open the .img file. Can anybody tell me how to open .img files?
Thanks in advance.
Sent from my GT-I9001 using XDA Premium App
martijn.vanpoorten said:
Hello, i want to edit some files in a recovery.img file but i cant open the .img file. Can anybody tell me how to open .img files?
Thanks in advance.
Sent from my GT-I9001 using XDA Premium App
Click to expand...
Click to collapse
Well, it depends of its internal format, can be samsung stock firmware format or not. You know it visually because is named factoryfs.img or system.img or either includes ext3 or ext4 or similar. Other times its yaffs filesystem.
Check here:
[HOW TO][Windows]Extract Deodex Sign and Zipalign an official ROM
From the Android device you can use AppExtractor or Nandroid Browser if it is in the proper filesystem format.
I think you must have a source for the recovery.img.
PhoneM96 said:
I think you must have a source for the recovery.img.
Click to expand...
Click to collapse
Not to just extract it.
scandiun said:
Well, it depends of its internal format, can be samsung stock firmware format or not. You know it visually because is named factoryfs.img or system.img or either includes ext3 or ext4 or similar. Other times its yaffs filesystem.
Check here:
[HOW TO][Windows]Extract Deodex Sign and Zipalign an official ROM
From the Android device you can use AppExtractor or Nandroid Browser if it is in the proper filesystem format.
Click to expand...
Click to collapse
Thanks for the info and pointing me into a direction, i will read the posts you added
scandiun said:
Not to just extract it.
Click to expand...
Click to collapse
PhoneM96 said:
I think you must have a source for the recovery.img.
Click to expand...
Click to collapse
I already have the recovery.img file i need. I only need to open it and see if i can make some changes to some files regarding the height and width. It looks like the version is build for an 7.1 tab
martijn.vanpoorten said:
I already have the recovery.img file i need. I only need to open it and see if i can make some changes to some files regarding the height and width. It looks like the version is build for an 7.1 tab
Click to expand...
Click to collapse
He means the source code of the img file, not the img. We already take for granted you already have it. Did you finally extract it?
scandiun said:
He means the source code of the img file, not the img. We already take for granted you already have it. Did you finally extract it?
Click to expand...
Click to collapse
Nope, still didn't extract it.
Here is what i have: recovery.tar.md5 I can open the file with winrar and extract the content and end up with the recovery.img file. How can i open the .img file and extract the content. I want to see what's inside and if i can edit the files, i want to learn more about it.
rename the md5 to tar and open it with winrar or peazip.
scandiun said:
He means the source code of the img file, not the img. We already take for granted you already have it. Did you finally extract it?
Click to expand...
Click to collapse
scandiun said:
rename the md5 to tar and open it with winrar or peazip.
Click to expand...
Click to collapse
I know that if when i rename .tar.md5 to just .tar i can use winrar to open the file. When the file is open i see a recovery.img file then i extrract the recovery.img to my desktop. How can i open the recovery.img file? I want to extract the content of the recovery.img file so i can see how it works and what is inside the recovery.img
martijn.vanpoorten said:
I know that if when i rename .tar.md5 to just .tar i can use winrar to open the file. When the file is open i see a recovery.img file then i extrract the recovery.img to my desktop. How can i open the recovery.img file? I want to extract the content of the recovery.img file so i can see how it works and what is inside the recovery.img
Click to expand...
Click to collapse
Try Diskinternals Linux Reader and mount the image with cntrol+m
This is exactly I want to do too. I only have the recovery.img but I want to modify the height and wight of it, because it designed for 7" and I want it to 10"... I managed to open it but looks like we need the source because I haven't found anything about it.
scandiun said:
Try Diskinternals Linux Reader and mount the image with cntrol+m
Click to expand...
Click to collapse
I can't open the file with DiskInternals Linux Reader.
Gaboros said:
This is exactly I want to do too. I only have the recovery.img but I want to modify the height and wight of it, because it designed for 7" and I want it to 10"... I managed to open it but looks like we need the source because I haven't found anything about it.
Click to expand...
Click to collapse
We are looking for the same thing
Another thing that would be nice is when the option to boot into recovery or download mode is added to the shutdown menu. I have CM9 on my phone and that has these options. It's very usefull ...
Try this script under linux or windows (you need perl installed) and see if you get "Android Magic not found" error.
[ADVANCED] How To Mod: BOOT & RECOVERY
Firmware Multi-booting
split_bootimg.pl
Code:
#!/usr/bin/perl
######################################################################
#
# File : split_bootimg.pl
# Author(s) : William Enck <[email protected]>
# Description : Split appart an Android boot image created
# with mkbootimg. The format can be found in
# android-src/system/core/mkbootimg/bootimg.h
#
# Thanks to alansj on xda-developers.com for
# identifying the format in bootimg.h and
# describing initial instructions for splitting
# the boot.img file.
#
# Last Modified : Tue Dec 2 23:36:25 EST 2008
# By : William Enck <[email protected]>
#
# Copyright (c) 2008 William Enck
#
######################################################################
use strict;
use warnings;
# Turn on print flushing
$|++;
######################################################################
## Global Variables and Constants
my $SCRIPT = __FILE__;
my $IMAGE_FN = undef;
# Constants (from bootimg.h)
use constant BOOT_MAGIC => 'ANDROID!';
use constant BOOT_MAGIC_SIZE => 8;
use constant BOOT_NAME_SIZE => 16;
use constant BOOT_ARGS_SIZE => 512;
# Unsigned integers are 4 bytes
use constant UNSIGNED_SIZE => 4;
# Parsed Values
my $PAGE_SIZE = undef;
my $KERNEL_SIZE = undef;
my $RAMDISK_SIZE = undef;
my $SECOND_SIZE = undef;
######################################################################
## Main Code
&parse_cmdline();
&parse_header($IMAGE_FN);
=format (from bootimg.h)
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
=cut
my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $k_offset = $PAGE_SIZE;
my $r_offset = $k_offset + ($n * $PAGE_SIZE);
my $s_offset = $r_offset + ($m * $PAGE_SIZE);
(my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;
my $k_file = $base . "-kernel";
my $r_file = $base . "-ramdisk.gz";
my $s_file = $base . "-second.gz";
# The kernel is always there
print "Writing $k_file ...";
&dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);
print " complete.\n";
# The ramdisk is always there
print "Writing $r_file ...";
&dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);
print " complete.\n";
# The Second stage bootloader is optional
unless ($SECOND_SIZE == 0) {
print "Writing $s_file ...";
&dump_file($IMAGE_FN, $s_file, $s_offset, $SECOND_SIZE);
print " complete.\n";
}
######################################################################
## Supporting Subroutines
=header_format (from bootimg.h)
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];
unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */
unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */
unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */
unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[2]; /* future expansion: should be 0 */
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
unsigned char cmdline[BOOT_ARGS_SIZE];
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
=cut
sub parse_header {
my ($fn) = @_;
my $buf = undef;
open INF, $fn or die "Could not open $fn: $!\n";
binmode INF;
# Read the Magic
read(INF, $buf, BOOT_MAGIC_SIZE);
unless ($buf eq BOOT_MAGIC) {
die "Android Magic not found in $fn. Giving up.\n";
}
# Read kernel size and address (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE * 2);
my ($k_size, $k_addr) = unpack("VV", $buf);
# Read ramdisk size and address (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE * 2);
my ($r_size, $r_addr) = unpack("VV", $buf);
# Read second size and address (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE * 2);
my ($s_size, $s_addr) = unpack("VV", $buf);
# Ignore tags_addr
read(INF, $buf, UNSIGNED_SIZE);
# get the page size (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE);
my ($p_size) = unpack("V", $buf);
# Ignore unused
read(INF, $buf, UNSIGNED_SIZE * 2);
# Read the name (board name)
read(INF, $buf, BOOT_NAME_SIZE);
my $name = $buf;
# Read the command line
read(INF, $buf, BOOT_ARGS_SIZE);
my $cmdline = $buf;
# Ignore the id
read(INF, $buf, UNSIGNED_SIZE * 8);
# Close the file
close INF;
# Print important values
printf "Page size: %d (0x%08x)\n", $p_size, $p_size;
printf "Kernel size: %d (0x%08x)\n", $k_size, $k_size;
printf "Ramdisk size: %d (0x%08x)\n", $r_size, $r_size;
printf "Second size: %d (0x%08x)\n", $s_size, $s_size;
printf "Board name: $name\n";
printf "Command line: $cmdline\n";
# Save the values
$PAGE_SIZE = $p_size;
$KERNEL_SIZE = $k_size;
$RAMDISK_SIZE = $r_size;
$SECOND_SIZE = $s_size;
}
sub dump_file {
my ($infn, $outfn, $offset, $size) = @_;
my $buf = undef;
open INF, $infn or die "Could not open $infn: $!\n";
open OUTF, ">$outfn" or die "Could not open $outfn: $!\n";
binmode INF;
binmode OUTF;
seek(INF, $offset, 0) or die "Could not seek in $infn: $!\n";
read(INF, $buf, $size) or die "Could not read $infn: $!\n";
print OUTF $buf or die "Could not write $outfn: $!\n";
close INF;
close OUTF;
}
######################################################################
## Configuration Subroutines
sub parse_cmdline {
unless ($#ARGV == 0) {
die "Usage: $SCRIPT boot.img\n";
}
$IMAGE_FN = $ARGV[0];
}
Here is my method for it.
First I used this tools.
http://www.mediafire.com/?9pllpht41e62d77
It is not my work, so sorry for reupolading but I didn't found the source!
Rename the recovery.img to boot.img (basically it was designed for this, but they the same) and put it there. And use the tool for unpack it for kernel and ramdisk.gz file.
Then You have to unpack it in linux (if I know well it is the best to do it there because if the filesystem)
For example:
"gunzip -c boot.img-ramdisk.gz | cpio -i"
It will unpack it, you have to do the necessarily changes. Than repack it:
"find . | cpio -o -H newc | gzip > ../newramdisk.cpio.gz"
Note this is pack the whole folder when you run it.
Then you just need to pack them back to img file.
But as I said I didn't found anything in connection with the resolution. It is quit sad because the recovery is working in my device but it designed for smaller screen and everything is display wrong.
It would be great if anyone know something about how to fix this without the source code, or someone could help me how to port the CWM from the original source.
This could help a bit to. But you got to mod the files a bit to you're device.
http://forum.xda-developers.com/showthread.php?t=1494036
[email protected] said:
This could help a bit to. But you got to mod the files a bit to you're device.
http://forum.xda-developers.com/showthread.php?t=1494036
Click to expand...
Click to collapse
Sorry for the late reply,
Thanks for the link and i will take a look at it again. I noticed that the best way is to use Linux. I had to reinstall Ubuntu firts but now it's all good to go
thanks man
Sent from my Nokia 5110 using Tapsilog and Kape
Beer Brand said:
thanks man
Sent from my Nokia 5110 using Tapsilog and Kape
Click to expand...
Click to collapse
i will be back to this soon..
Sent from my Transformer TF101 using Tapatalk HD
Related
I'm trying to build a kernel for my y301-a2 but I get a perl error, i fixed most of the errors but this one keeps coming back
readline() on closed filehandle FXML at parse_product_id.pl on line 19
this is the file in question
Code:
#!/usr/bin/perl -w
sub back_trim
{
my $slash_pos = rindex($_[0], $_[1]);
return substr($_[0], 0, $slash_pos);
}
#open ARGV[1]
open FXML, "<$ARGV[0]" || die "can't open $ARGV[0]! please check your command and filesystem.";
open FOUT, ">config_total_product.c" || die "can't open config_total_product.c";
open FBOARDIDS, ">../../../include/hsad/config_boardids.h" || die "can't open board ids header file";
my $max_board_id0 =0;
my $max_board_id1 =0;
my %products;
my $xml_path;
while(<FXML>)
{
chomp;
# only match once: <products max_board_id0="6" max_board_id1="6">
if ($max_board_id0 == 0 && /^\s*<products\s+max_board_id0\s*=\s*\"(\d+)\"\s+max_board_id1\s*=\s*\"(\d+)\"\s*>\s*$/i)
{
$max_board_id0=$1;
$max_board_id1=$2;
}
# <product board_id0="$1" board_id1="$2">product_name</product>
if (/^\s*<product\s+board_id0\s*=\s*\"(\d+)\"\s+board_id1\s*=\s*\"(\d+)\"\s*>(\w+)<\/product>\s*$/i)
{
$board_id0=$1;
$board_id1=$2;
$product_name=$3;
if ($max_board_id1 < 16)
{
$board_id_key = $board_id0 * 16 + $board_id1;
}
else
{
$board_id_key = $board_id0 * ($max_board_id1+1) + $board_id1;
}
$products{$board_id_key} = $product_name;
}
}
close FXML;
$xml_path = &back_trim($ARGV[0], "/");
$xml_path = $xml_path."/";
#generate every product configs
foreach $product (values %products) {
system("perl parse_product.pl ".$xml_path.$product."/kernel/hw_".$product."_configs.xml");
}
#now we got a hash table contain all the product name; then we can print the target file.
select FOUT;
print "/* This file is auto-generated by tool, please don't manully modify it.*/\n\n";
#print board id definition
#foreach $board_id (keys %products) {
# print "#define BOARD_ID_".uc($products{$board_id})." ".$board_id."\n";
#}
#print board id header file includes
print "#include <hsad/config_boardids.h>\n\n";
#retrive the product names in hash table, include them all.
foreach $product (values %products) {
print "#include \"hw_".$product."_configs.c\"\n";
}
print "#ifdef CONFIG_HW_POWER_TREE\n";
foreach $product (values %products) {
print "extern struct board_id_general_struct config_power_".$product.";\n";
}
print "#endif\n";
#generate gpio data
print "\n/*gpio perl producted data*/\n";
print "#ifdef CONFIG_HUAWEI_GPIO_UNITE\n";
foreach $product (values %products) {
print "extern struct board_id_general_struct config_gpio_".$product.";\n";
print "extern struct board_id_general_struct config_pm_gpio_".$product.";\n";
}
print "#endif\n";
print "\n";
#generate total config data, ATTENTION: if you want to add new data structure in hsad, also also data here:
print "/*total table*/\n";
print "struct board_id_general_struct *hw_ver_total_configs[] = \n";
print "{\n";
my $indent = " ";
#part 1: gpio data:
print "#ifdef CONFIG_HUAWEI_GPIO_UNITE\n";
foreach $product (values %products) {
print $indent."&config_gpio_".$product.", //gpio\n";
}
print "#endif\n";
print "#ifdef CONFIG_HUAWEI_GPIO_UNITE\n";
foreach $product (values %products) {
print $indent."&config_pm_gpio_".$product.", //pm gpio\n";
}
print "#endif\n";
#part 2: common data:
foreach $product (values %products) {
print $indent."&config_common_".$product.", //common xml\n";
}
print "#ifdef CONFIG_HW_POWER_TREE\n";
foreach $product (values %products) {
print $indent."&config_power_".$product.",\n";
}
print "#endif\n";
print "};\n";
close FOUT;
#output board ids to include/hsad/config_boardids.h
select FBOARDIDS;
print "/* This file is auto-generated by tool, DO NOT modify it manully. */\n\n";
print "#ifndef CONFIG_BOARDIDS_H\n";
print "#define CONFIG_BOARDIDS_H\n\n";
foreach $board_id (keys %products) {
print "#define BOARD_ID_".uc($products{$board_id})." ".$board_id."\n";
}
print "\n";
print "#endif\n";
anyone have any idea what could be causing it.
I also found this readme for it but I can't read it, and translating does not work too well
Code:
comdef.h ---- ヘィモテハセンタ獎ヘオトカィメ・
config_interface.h ---- スモソレイ耋キホトシ
config_mgr.h --- ハセンケワタ昀耋キホトシ」サ
configdata.h --- クテト」ソ鯑レイソハセンス盪ケカィメ蠏トヘキホトシ」サ
hwconfig_enum.h --- ナ葷テア昤ミオトテカセルミヘカィメ螢ャソノメヤー・ャニ萢遧トト」ソ魴トヘキホトシ
hw_msm8960_configs.xml --- msm8960オトナ葷テハセン
hw_msm8960_configs.xml --- msm8960オトナ葷テハセン
product_bootid.xml --- ク憘キコヘboot idオトカヤモヲケリマオ
hw_msm8960_configs.c --- msm8960オトナ葷テハセン
hw_msm8960_configs.c --- msm8960オトナ葷テハセン
hw_ver_total_config.c --- ヒミイ憘キオトナ葷テハセン
parse_prudct.pl --- スォク憘キオトxmlナ葷テハセンラェウノcホトシナ葷テハセン
parse_product_id.pl --- ノ嵭ノhw_ver_total_config.cホトシ
config_mgr.c --- ハセンケワタ昀飜オマヨ
config_interface.c --- スモソレイ飜オマヨ
after looking into this some more it seems that instead of using different defconfigs for every device huawei is using 1 defconfig and then a separate perl script to load configs that change the drivers while building(I guess so they can use 1 defconfig for every devicemsm8930 device they have I think) I am pretty sure a command has to be run before building to config this but I don't know it, has anyone ever dealt with this before.
anyone
this is the github with the perl script by the way
https://github.com/KainXS/android_kernel_huawei_y301a2/tree/jellybean/drivers/huawei/hsad
I wish i could!
Please, can you help me!
This long I'm looking for a solution to put in the place the integrated camera of the pc that persists to be upside down!
I was able to find information that could be useful to developers but I do not know how to apply them with Remix OS!
Is anyone could help me please?
I found sources to patch the camera on a site of ubuntu.
https://ubuntuforums.org/showthread.php?t=838210
I do not know which of these patches would likely work with my equipment
Is there someone who knows it in Linux or android who can give me information
Or is that the developer of Remix OS could do some things for me to solve this problem?
Thank you for your attention
cordially
Jean Pierre
FIRST SOLUTION (MIRRORED IMAGES)
# modified June 26, 2008
Code:
diff -uN UVCVIDEO_v0.1.0/uvc_video.c UVCVIDEO_patched/uvc_video.c
--- UVCVIDEO_v0.1.0/uvc_video.c 2008-06-26 10:41:01.000000000 +0200
+++ UVCVIDEO_patched/uvc_video.c 2008-06-26 15:33:33.000000000 +0200
@@ -371,23 +371,92 @@
return data[0];
}
+/* This patched function allows to overturn video images from an upside-down
+ * orientation to a normal one with mirrored effect. The conversion simply
+ * consists in reversing the order of the rows of imagines.
+ * This patch performs its job just once for each frame and only when current
+ * frame is completed, but each time it is required to allocate memory in order
+ * to store a copy of that frame.
+ * This patch should work with all YUV image formats.
+ */
static void uvc_video_decode_data(struct uvc_video_device *video,
struct uvc_buffer *buf, const __u8 *data, int len)
{
struct uvc_video_queue *queue = &video->queue;
unsigned int maxlen, nbytes;
void *mem;
+ /* Patch variables */
+ __u8 *mem_tmp, *ptr_tmp;
+ int i, k, row_size;
if (len <= 0)
return;
/* Copy the video data to the buffer. */
+ /* How many bytes are needed to complete the buffer? */
maxlen = buf->buf.length - buf->buf.bytesused;
+ /* Where do pixels stored in "data" have to be copied? */
mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ /* How many bytes really can be copied into "mem"? */
nbytes = min((unsigned int)len, maxlen);
+ /* "nbytes" are copied from "data" to "mem" buffer.
+ * "data" stores a sequence of pixels coming from the video source.
+ * This sequence is not a full frame or a full row of pixel, but just an
+ * ordered vector of pixels (from top-left to bottom-right), whose
+ * represents just an area of the current frame.
+ * This function has to be called hundreds of times before a frame is
+ * completed and "nbytes" is not constant! Each time "data" contains the
+ * next part of the frame. At the end data stored in "mem" buffer will
+ * be used by the application who requested the video stream.
+ */
memcpy(mem, data, nbytes);
buf->buf.bytesused += nbytes;
+ /* Have the last copied bytes completed the current frame? */
+ if (nbytes == maxlen) {
+ /* Area where to save the upper half part of the original frame
+ * (just half in order to speed up the patch) before reversing.
+ */
+ mem_tmp = (__u8 *) kmalloc(buf->buf.bytesused / 2, GFP_ATOMIC);
+ if (mem_tmp != NULL ) {
+ /* Copy top-half part of frame in a temporary buffer */
+ memcpy(mem_tmp, queue->mem + buf->buf.m.offset,
+ buf->buf.bytesused / 2);
+ /* "row_size" does not depend only on the width of the
+ * frame, but also on the pixel color depth (bpp).
+ */
+ row_size = video->streaming->cur_frame->wWidth *
+ video->streaming->format->bpp / 8;
+ /* The following cycle just copy full frame rows from
+ * the last one stored in "mem" (and going up) to the
+ * first one (and going down) stored in "mem" itself.
+ */
+ ptr_tmp = queue->mem + buf->buf.m.offset
+ + buf->buf.bytesused / 2;
+ /* When the top-half of the frame has been reversed,
+ * rows are copied from the last one stored in "mem_tmp"
+ * (and going up) into the bottom half part of "mem"
+ * buffer.
+ */
+ for (i = 0, k = buf->buf.bytesused / 2 - row_size;
+ i < buf->buf.bytesused;
+ i += row_size, k -= row_size) {
+ /* If the top-half of the frame has been
+ * revesed, then it is needed to split the
+ * source buffer from "mem" to "mem_tmp".
+ */
+ if (i == buf->buf.bytesused / 2) {
+ ptr_tmp = mem_tmp;
+ k = buf->buf.bytesused / 2 - row_size;
+ }
+ memcpy(queue->mem + buf->buf.m.offset + i,
+ ptr_tmp + k,
+ row_size);
+ }
+ /* For this frame "mem_tmp" is not needed any more. */
+ kfree(mem_tmp);
+ }
+ }
/* Complete the current frame if the buffer size was exceeded. */
if (len > maxlen) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
FIRST SOLUTION (NOT MIRRORED IMAGES)
# modified June 26, 2008
Code:
diff -uN UVCVIDEO_v0.1.0/uvc_video.c UVCVIDEO_patched/uvc_video.c
--- UVCVIDEO_v0.1.0/uvc_video.c 2008-06-26 10:41:01.000000000 +0200
+++ UVCVIDEO_patched/uvc_video.c 2008-06-26 15:33:33.000000000 +0200
@@ -371,23 +371,105 @@
return data[0];
}
+/* This patch should work ONLY with YUY2 image formats, also known as YUYV or
+ * YUV422 formats.
+ * This patched function allows to overturn video images from an upside-down
+ * orientation to a normal one. The conversion consists in copying 4 bytes at a
+ * time (Y0,U0,Y1,V0) corresponding to 2 pixels, in a bottom-up direction, from
+ * the frame (coming from the video source) to the buffer that will be used by
+ * the application requesting the video stream. But in order to satisfy the YUY2
+ * image format byte has to be copied in this way: Y1 U0 Y0 VO.
+ * This patch performs its job just once for each frame and only when current
+ * frame is completed, but each time it is required to allocate memory in order
+ * to store a copy of that frame.
+ */
static void uvc_video_decode_data(struct uvc_video_device *video,
struct uvc_buffer *buf, const __u8 *data, int len)
{
struct uvc_video_queue *queue = &video->queue;
unsigned int maxlen, nbytes;
void *mem;
+ /* Patch variables */
+ __u8 *mem_tmp, *ptr_tmp;
+ int i, k, pixel_size;
if (len <= 0)
return;
/* Copy the video data to the buffer. */
+ /* How many bytes are needed to complete the buffer? */
maxlen = buf->buf.length - buf->buf.bytesused;
+ /* Where do pixels stored in "data" have to be copied? */
mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ /* How many bytes really can be copied into "mem"? */
nbytes = min((unsigned int)len, maxlen);
+ /* "nbytes" are copied from "data" to "mem" buffer.
+ * "data" stores a sequence of pixels coming from the video source.
+ * This sequence is not a full frame or a full row of pixel, but just
+ * an ordered vector of pixels (from top-left to bottom-right), whose
+ * represents just an area of the current frame.
+ * This function has to be called hundreds of times before a frame is
+ * completed and "nbytes" is not constant! Each time "data" contains the
+ * next part of the frame. At the end data stored in "mem" buffer will
+ * be used by the application who requested the video stream.
+ */
memcpy(mem, data, nbytes);
buf->buf.bytesused += nbytes;
+ /* Have the last copied bytes completed the current frame? */
+ if (nbytes == maxlen) {
+ /* Area where to save the original frame before manipulation. */
+ mem_tmp = (__u8 *) kmalloc(buf->buf.bytesused / 2, GFP_ATOMIC);
+ if (mem_tmp != NULL ) {
+ /* Copy the original frame in a temporary buffer. */
+ memcpy(mem_tmp, queue->mem + buf->buf.m.offset,
+ buf->buf.bytesused / 2);
+ /* "pixel_size" depens on the pixel color depth (bpp),
+ * but in YUY2 image format is constant and equal to 2.
+ */
+ pixel_size = video->streaming->format->bpp / 8;
+ /* The following loop copy 2 pixels at a time (4 bytes
+ * in YUY2 format) from the last two stored in "mem"
+ * (and going back) to the first two (and going on)
+ * stored in "mem" itself following a sort of YUY2
+ * algorithm.
+ */
+ ptr_tmp = queue->mem + buf->buf.m.offset
+ + buf->buf.bytesused / 2;
+ /* When the top-half of the frame has been reversed,
+ * rows are copied from the last one stored in "mem_tmp"
+ * (and going up) into the bottom half part of "mem"
+ * buffer.
+ */
+ for (i = 0, k = buf->buf.bytesused / 2 - 2 * pixel_size;
+ i < buf->buf.bytesused;
+ i += 2 * pixel_size, k -= 2 * pixel_size){
+ /* If the top-half of the frame has been
+ * revesed, then it is needed to split the
+ * source buffer from "mem" to "mem_tmp".
+ */
+ if (i == buf->buf.bytesused / 2) {
+ ptr_tmp = mem_tmp;
+ k = buf->buf.bytesused / 2
+ - 2 * pixel_size;
+ }
+ /* The order of copied bytes is changed from
+ * (Y0 U0 Y1 V1) to (Y1 U0 Y0 V1), i.e. from
+ * (#0 #1 #2 #3) to (#2 #1 #0 #3).
+ */
+ ((__u8 *)(queue->mem+buf->buf.m.offset + i))[0] =
+ ((__u8 *)(ptr_tmp + k))[2];
+ ((__u8 *)(queue->mem+buf->buf.m.offset + i))[1] =
+ ((__u8 *)(ptr_tmp + k))[1];
+ ((__u8 *)(queue->mem+buf->buf.m.offset + i))[2] =
+ ((__u8 *)(ptr_tmp + k))[0];
+ ((__u8 *)(queue->mem+buf->buf.m.offset + i))[3] =
+ ((__u8 *)(ptr_tmp + k))[3];
+ }
+ /* For this frame "mem_tmp" is not needed any more. */
+ kfree(mem_tmp);
+ }
+ }
/* Complete the current frame if the buffer size was exceeded. */
if (len > maxlen) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
SECOND SOLUTION (MIRRORED IMAGES)
# modified June 26, 2008
Code:
diff -uN UVCVIDEO_v0.1.0/uvc_video.c UVCVIDEO_patched/uvc_video.c
--- UVCVIDEO_v0.1.0/uvc_video.c 2008-06-26 10:41:01.000000000 +0200
+++ UVCVIDEO_patched/uvc_video.c 2008-06-26 14:03:58.000000000 +0200
@@ -371,23 +371,91 @@
return data[0];
}
+/* This patched function allows to overturn video images from an upside-down
+ * orientation to a normal one with mirrored effect. The conversion consists in
+ * reversing the order of the rows of imagines.
+ * "data" stores a sequence of pixels coming from the video source.
+ * This sequence is not a full frame or a full row of pixel, but just an
+ * ordered vector of pixels (from top-left to bottom-right), whose
+ * represents just an area of the current frame and which size ("nbytes") is
+ * not constant. In fact this function has to be called hundreds of times
+ * before a frame is completed. Each time "data" contains the next part of the
+ * current frame (upside-down). At the end data stored in "mem" buffer will be
+ * used by the application who requested the video stream.
+ * No memory allocation is needed because pixel order is modified directly
+ * while copying from "data" into "mem" buffer (i.e. in each call of this
+ * function), and not just once when the frame is already completed.
+ * This patch should work with all YUV image formats.
+ */
static void uvc_video_decode_data(struct uvc_video_device *video,
struct uvc_buffer *buf, const __u8 *data, int len)
{
struct uvc_video_queue *queue = &video->queue;
unsigned int maxlen, nbytes;
void *mem;
+ /* Patch variables */
+ unsigned int row_size, to_be_copied, shift_right;
if (len <= 0)
return;
/* Copy the video data to the buffer. */
+ /* How many bytes are needed to complete the buffer? */
maxlen = buf->buf.length - buf->buf.bytesused;
+ /* Where do pixels stored in "data" have to be copied? */
mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ /* How many bytes really can be copied into "mem"? */
nbytes = min((unsigned int)len, maxlen);
- memcpy(mem, data, nbytes);
- buf->buf.bytesused += nbytes;
+ /* "row_size" is the number of bytes required to store a full row of
+ * the frame.
+ */
+ row_size = video->streaming->cur_frame->wWidth *
+ video->streaming->format->bpp / 8;
+ /* Each loop "nbytes" is decremented of the number of bytes just copied.
+ * So are there any other bytes to be copied?
+ */
+ while (nbytes > 0) {
+ /* As the rows of modified frames have to be fulfilled from
+ * bottom-left to top-right, each cycle tries to complete a
+ * single row.
+ * In this cycle where is it needed to start to store bytes
+ * within the selected row? From the beginning or shifted
+ * right? Because other bytes could have been already stored in
+ * that row without completing it, so it could be needed a right
+ * shift.
+ */
+ shift_right = buf->buf.bytesused % row_size;
+ /* In this cycle how many byte can we copy in the selected row?
+ */
+ if (nbytes > row_size - shift_right)
+ to_be_copied = row_size - shift_right ;
+ else
+ to_be_copied = nbytes;
+ /* "queue->mem + buf->buf.m.offset" is the base-address where to
+ * start to store the current frame. This address refers to a
+ * preallocated area (just for a sigle frame) taking part in a
+ * circular buffer, where to store a fixed number of sequent
+ * frames.
+ */
+ memcpy(queue->mem + buf->buf.m.offset
+ /* Go to the end of this frame. */
+ + row_size * video->streaming->cur_frame->wHeight
+ /* Go back for the number of bytes corrisponding to the
+ * already fully completed rows.
+ */
+ - (buf->buf.bytesused - shift_right)
+ /* Go back at the starting point of the upper row. */
+ - row_size
+ /* Shift right on this row if it is needed. */
+ + shift_right,
+ data,
+ to_be_copied );
+ /* Update "data", "byteused" and "nbytes" values. */
+ data += to_be_copied;
+ buf->buf.bytesused += to_be_copied ;
+ nbytes -= to_be_copied;
+ }
/* Complete the current frame if the buffer size was exceeded. */
if (len > maxlen) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
SECOND SOLUTION (NOT MIRRORED IMAGES)
# modified June 26, 2008
Code:
diff -uN UVCVIDEO_v0.1.0/uvc_video.c UVCVIDEO_patched/uvc_video.c
--- UVCVIDEO_v0.1.0/uvc_video.c 2008-06-26 10:41:01.000000000 +0200
+++ UVCVIDEO_patched/uvc_video.c 2008-06-26 14:03:58.000000000 +0200
@@ -371,23 +371,81 @@
return data[0];
}
+/* This patch should work ONLY with YUY2 image formats, also known as YUYV or
+ * YUV422 formats.
+ * This patched function allows to overturn video images from an upside-down
+ * orientation to a normal one. The conversion consists in copying 4 bytes at a
+ * time (Y0,U0,Y1,V0) corresponding to 2 pixels from the frame (coming from the
+ * video source) to the buffer that will be used by the application requesting
+ * the video stream. But in order to satisfy the YUY2 image format byte has to
+ * be copied in this way: Y1 U0 Y0 VO. Bytes are copied in a bottom-up
+ * direction into the reversed frame.
+ * "data" stores a sequence of pixels coming from the video source.
+ * This sequence is not a full frame or a full row of pixel, but just an
+ * ordered vector of pixels (from top-left to bottom-right), whose
+ * represents just an area of the current frame and which size ("nbytes") is
+ * not constant. In fact this function has to be called hundreds of times
+ * before a frame is completed. Each time "data" contains the next part of the
+ * current frame (upside-down). At the end data stored in "mem" buffer will be
+ * used by the application who requested the video stream.
+ * No memory allocation is needed because pixel order is modified directly
+ * while copying from "data" into "mem" buffer (i.e. in each call of this
+ * function), and not just once when the frame is already completed.
+ */
static void uvc_video_decode_data(struct uvc_video_device *video,
struct uvc_buffer *buf, const __u8 *data, int len)
{
struct uvc_video_queue *queue = &video->queue;
unsigned int maxlen, nbytes;
void *mem;
+ /* Patch variables */
+ unsigned int i, pixel_size;
+ __u8 *ptr_tmp;
if (len <= 0)
return;
/* Copy the video data to the buffer. */
+ /* How many bytes are needed to complete the buffer? */
maxlen = buf->buf.length - buf->buf.bytesused;
+ /* Where do pixels stored in "data" have to be copied? */
mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ /* How many bytes really can be copied into "mem"? */
nbytes = min((unsigned int)len, maxlen);
- memcpy(mem, data, nbytes);
- buf->buf.bytesused += nbytes;
+ /* "pixel_size" depens on the pixel color depth (bpp),
+ * but in YUY2 image format is constant and equal to 2.
+ */
+ pixel_size = video->streaming->format->bpp / 8;
+ /* In each loop 4 bytes are modified and copied into "mem" buffer. */
+ for (i = 0; i < nbytes; i += 2 * pixel_size) {
+ /* "queue->mem + buf->buf.m.offset" is the base-address
+ * where to start to store the current frame. This
+ * address refers to a preallocated area (just for a
+ * sigle frame) taking part in a circular buffer, where
+ * to store a fixed number of sequent frames.
+ */
+ ptr_tmp = (__u8 *)(queue->mem + buf->buf.m.offset
+ /* Go to the end of this frame. */
+ + video->streaming->cur_frame->wWidth * pixel_size
+ * video->streaming->cur_frame->wHeight
+ /* Go back for the number of already copied bytes. */
+ - buf->buf.bytesused
+ /* Go back for the number of bytes (4 bytes) to be
+ * copied in this cycle.
+ */
+ - 2 * pixel_size);
+ /* The order of copied bytes is changed from
+ * (Y0 U0 Y1 V1) to (Y1 U0 Y0 V1), i.e. from
+ * (#0 #1 #2 #3) to (#2 #1 #0 #3).
+ */
+ ptr_tmp[0] = ((__u8 *)(data + i))[2];
+ ptr_tmp[1] = ((__u8 *)(data + i))[1];
+ ptr_tmp[2] = ((__u8 *)(data + i))[0];
+ ptr_tmp[3] = ((__u8 *)(data + i))[3];
+ /* Update "byteused" value. */
+ buf->buf.bytesused += 2 * pixel_size;
+ }
/* Complete the current frame if the buffer size was exceeded. */
if (len > maxlen) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
"
Well, now the worst part has been done!!!
We just need to compile our modded file and to install the new driver, so from shell you have to go to the "Trunk" directory and type:
Code:
make
there shouldn't be errors!!
Then, ONLY if you are using one of the Ubuntu distributions (ubuntu, kubuntu, etc.), open with you editor the "Makefile" and change the following line:
Code:
INSTALL_MOD_DIR := usb/media
with
Code:
INSTALL_MOD_DIR := ubuntu/media/usbvideo
Now we just need to remove uvcvideo module (if you have previously installed it):
Code:
sudo modprobe -r uvcvideo
Then:
Code:
sudo make install
sudo cp uvcvideo.ko /lib/modules/`uname -r`/ubuntu/media/usbvideo/
sudo cp uvcvideo.ko /lib/modules/`uname -r`/usb/media/
sudo depmod -ae
sudo modprobe -f uvcvideo
Now everything should work!!!
Let me know!!
And please try both solutions..
in case you don't see any difference just use the SECOND solution (mirrored or not, has you prefer), it should be the safest!!
Good luck,
enjoy your webcam!!
"
I continue my investigations and I find the place concerned that manages the camera's drivers can be found here:
/lib/modules/4.4.14-android-x86_64/kernel/drivers/media/usb/uvc
uvcvideo.ko
but for now, I am not able to apply the patch because I do not know if Remix OS has the necessary tools.
Can anyone answer this question
thank you
cordially
Jean Pierre
Basically, there has been an app ported to Android that allows even unrooted(stock) devices to deliver a bootrom exploit to the Nintendo Switch via USB-OTG and a USB cable (or C-to-C). USB 3.0 (xHCI) devices have no issues and deliver the exploit just fine. Apparently it is not even a USB 2.0 problem but rather how the EHCI performs, as certain USB 2.0 phones actually have the xHCI controller and can run the exploit just fine. What happens is that although it can detect the connected Switch in Tegra Recovery Mode, it just doesn't do anything and gives an error in the logs, "SUMBITURB failed".
On Linux desktop systems it is similar, but the exploit can still work with a kernel patch provided by a hacking group that discovered the exploit in the first place:
Code:
--- linux-4.14.27/drivers/usb/host/ehci-hcd.c.old 2018-04-17 18:00:00.000000000 +0000
+++ linux-4.14.27/drivers/usb/host/ehci-hcd.c 2018-04-17 18:00:00.000000000 +0000
@@ -873,14 +873,6 @@
INIT_LIST_HEAD (&qtd_list);
switch (usb_pipetype (urb->pipe)) {
- case PIPE_CONTROL:
- /* qh_completions() code doesn't handle all the fault cases
- * in multi-TD control transfers. Even 1KB is rare anyway.
- */
- if (urb->transfer_buffer_length > (16 * 1024))
- return -EMSGSIZE;
- /* FALLTHROUGH */
- /* case PIPE_BULK: */
default:
if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
return -ENOMEM;
The author of the Android port had also written a Python "hotpatch" script for desktop Linux systems:
Code:
#!/usr/bin/env python3
import os
"""
Cursed Code.
This code literally patches your kernel memory, proceed at your own risk.
Tested on Ubuntu 17.10 and Arch, x86_64. Should work on other distros, maybe even other architectures!
Run fusee-launcher.py with the "--override-checks" argument.
If you'd rather patch your drivers properly:
https://github.com/fail0verflow/shofel2/blob/master/linux-ehci-enable-large-ctl-xfers.patch
"""
ksyms = {
line[2]: int(line[0], 16)
for line in
map(lambda l: l.strip().split(),
open("/proc/kallsyms", "r").readlines())}
print(hex(ksyms["ehci_urb_enqueue"]))
patch_c = """
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/pgtable.h>
static u32 ORIG_MAX = 16*1024;
static u32 NEW_MAX = 0x1000000;
/* borrowed from MUSL because I'm lazy AF */
static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=3, k-=3; k; k--, hw = hw<<8 | *++h)
if (hw == nw) return (char *)h-3;
return 0;
}
static pte_t* (*lookup_addr)(unsigned long, unsigned int*) = (void *) PLACE2;
static void set_addr_rw(unsigned long addr) {
unsigned int level;
pte_t *pte = lookup_addr(addr, &level);
set_pte_atomic(pte, pte_mkwrite(*pte));
}
int init_module(void) {
void * ehci_urb_enqueue_start = (void *) PLACEHOLDER;
u32 * patch_addr;
printk(KERN_INFO "Patch module loaded\\n");
patch_addr = (u32 *) fourbyte_memmem(ehci_urb_enqueue_start, 0x400, (void *)&ORIG_MAX);
if (patch_addr == NULL) {
printk(KERN_INFO "Failed to find patch site :(\\n");
return -1;
}
printk(KERN_INFO "patch_addr: 0x%px\\n", patch_addr);
set_addr_rw((unsigned long)patch_addr);
*patch_addr = NEW_MAX;
printk(KERN_INFO "Patching done!\\n");
return -1;
}
""".replace("PLACEHOLDER", hex(ksyms["ehci_urb_enqueue"])).replace("PLACE2", hex(ksyms["lookup_address"]))
makefile = """
obj-m += patch.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
"""
with open("patch.c", "w") as patchfile:
patchfile.write(patch_c)
with open("Makefile", "w") as mf:
mf.write(makefile)
os.system("make")
print("About to insert patch module, 'Operation not permitted' means it probably worked, check dmesg output.")
os.system("insmod patch.ko")
I tried to see if running it in Termux would do anything but I got the following error:
Code:
0x0
Traceback (most recent call last):
File "ehci_patch.py", line 70, in <module>
" " ".replace("PLACEHOLDER", hex(ksyms["ehci_urb_enqueue"])).replace("PLACE2" hex(ksyms["lookup_address"]))
KeyError: 'lookup_address'
I know that script isn't meant for use on Android anyway but maybe it can lead to a solution. The author of it does not know how to go about it at this time either, but believes an entire recompile of the kernel would be necessary. I am hoping that something like a systemless Magisk module would be the easiest solution for users but do not know if that is possible. I am only guessing it might be possible to create a Magisk module because of audio drivers like VIPER4Android. If indeed a custom kernel is needed, does anyone know how to go about it? It could be difficult to implement for everyone because not everyone has a device where the source to the kernel is available, etc. I am willing, however, to test anything on my tablet which is USB 2.0 and gives the error in the app. Any advice for how to go about this will be greatly appreciated.
I feel ya man, i need this stuff too. NXLoader doesn't work on my Galaxy Grand Prime (G530T) and i really need it to Dx
Hello ... so i have an Radio.img and i know inside there are this files
(bootloader) Validating 'radio.default.xml'
(bootloader) Committing 'radio.default.xml'
(bootloader) - flashing 'NON-HLOS.bin' to 'modem'
(bootloader) - flashing 'fsg.mbn' to 'fsg'
(bootloader) - erasing 'modemst1'
(bootloader) - erasing 'modemst2'.
How can i extract NON-HLOS and fsg ? thanks in advance ...
I know this is an ancient thread, but it's still the first search result, so I figured a solution could help anyone else that stumbles upon this..
I made a quick and dirty extractor that works at least for motorola edge 2021 xt2141 radio images. These files seem to start with magic "SINGLE_N_LONELY" and end with "LONELY_N_SINGLE". Filenames are provided, followed by the length of the contents (in little endian), then the contents.
This script will try to open radio.img in the current dir if a filename is not provided. Dumped files will go right in the working dir, so be careful. File content reading isn't done in chunks here, so be mindful of memory usage. Likely not an issue, but you can code in some chunking if needed.
Code:
#!/usr/bin/env python
import io
import sys
# supply filename as argument or default to 'radio.img'
try:
filename = sys.argv[1]
except IndexError:
filename = 'radio.img'
with open(filename, 'rb') as f:
magic = f.read(0x100).strip(b'\0').decode()
print(magic)
assert magic == 'SINGLE_N_LONELY'
while True:
# filename
fn = f.read(0xF0).strip(b'\0').decode()
print(fn)
if fn == 'LONELY_N_SINGLE':
break
# size of file in little endian
f.seek(0x08, io.SEEK_CUR)
l = int.from_bytes(f.read(0x08), 'little')
print(l)
# warning: not reading in chunks...
# warning: outputs to working dir
with open(fn, 'wb') as o:
o.write(f.read(l))
# seek remainder
rem = 0x10 - (l % 0x10)
if rem < 0x10:
f.seek(rem, io.SEEK_CUR)
# seek until next filename
while not f.read(0x10).strip(b'\0'):
continue
# rewind back to start of filename
f.seek(-0x10, io.SEEK_CUR)
Note the resulting images will likely be in sparse format. You'll need simg2img to convert to raw images if you're trying to mount or otherwise manhandle the images.
If interested in dumping carrier profiles (from inside the fsg image), EfsTools has an extractMbn function. Not sure how to reassemble though. https://github.com/JohnBel/EfsTools
ziddey said:
I know this is an ancient thread, but it's still the first search result, so I figured a solution could help anyone else that stumbles upon this..
I made a quick and dirty extractor that works at least for motorola edge 2021 xt2141 radio images. These files seem to start with magic "SINGLE_N_LONELY" and end with "LONELY_N_SINGLE". Filenames are provided, followed by the length of the contents (in little endian), then the contents.
This script will try to open radio.img in the current dir if a filename is not provided. Dumped files will go right in the working dir, so be careful. File content reading isn't done in chunks here, so be mindful of memory usage. Likely not an issue, but you can code in some chunking if needed.
Code:
#!/usr/bin/env python
import io
import sys
# supply filename as argument or default to 'radio.img'
try:
filename = sys.argv[1]
except IndexError:
filename = 'radio.img'
with open(filename, 'rb') as f:
magic = f.read(0x100).strip(b'\0').decode()
print(magic)
assert magic == 'SINGLE_N_LONELY'
while True:
# filename
fn = f.read(0xF0).strip(b'\0').decode()
print(fn)
if fn == 'LONELY_N_SINGLE':
break
# size of file in little endian
f.seek(0x08, io.SEEK_CUR)
l = int.from_bytes(f.read(0x08), 'little')
print(l)
# warning: not reading in chunks...
# warning: outputs to working dir
with open(fn, 'wb') as o:
o.write(f.read(l))
# seek remainder
rem = 0x10 - (l % 0x10)
if rem < 0x10:
f.seek(rem, io.SEEK_CUR)
# seek until next filename
while not f.read(0x10).strip(b'\0'):
continue
# rewind back to start of filename
f.seek(-0x10, io.SEEK_CUR)
Note the resulting images will likely be in sparse format. You'll need simg2img to convert to raw images if you're trying to mount or otherwise manhandle the images.
If interested in dumping carrier profiles (from inside the fsg image), EfsTools has an extractMbn function. Not sure how to reassemble though. https://github.com/JohnBel/EfsTools
Click to expand...
Click to collapse
Thanks for making python script to unpack these SINGLE_N_LONELY header files(bootloader.img, radio.img, singleimage.bin, gpt.bin) from Moto Stock ROM zips.
But why reading filename only 240 bytes and skipping 8 bytes instead of reading whole 248 bytes?
This guy wrote to read 248 bytes instead https://forum.xda-developers.com/t/...t-of-the-moto-g-5g-plus.4371213/post-87807175
I also made quick and dirty unpacked using Lua 5.3 at https://forum.xda-developers.com/t/...t-of-the-moto-g-5g-plus.4371213/post-87931915
I guess one of us has to post this to github, since I can't find any Open Source tool to unpack this simple format image files.
Currently, only star tool that we can find from some of blankflash files(eg. this) and imjtool can unpack these SINGLE_N_LONELY header files as far as I know. But I guess these are not Open Source.
Thanks
HemanthJabalpuri said:
But why reading filename only 240 bytes and skipping 8 bytes instead of reading whole 248 bytes?
This guy wrote to read 248 bytes instead https://forum.xda-developers.com/t/...t-of-the-moto-g-5g-plus.4371213/post-87807175
Click to expand...
Click to collapse
Ah neat. I only used xt2141 radio images as reference for approximating the file format. It's been a while, but I think based on the actual positioning of the filenames in the images I was testing, I wasn't sure if the final 8 bytes were part of the filename or padding.
Likewise, I wasn't sure of how padding works after the file data, so I just did a dumb seek and rewind.
Windows 11 how do I make all files and folders appear as General items and always sorted by date modified and detailed view?
I'm doing the usual ways through file options, but it doesn't work.
In all folders and for some reason it doesn't remember what settings I saved. Is there a way or reg file to make it sealed in the system and that can't be changed?
Chat gpt gave this yet to try ( didn't worked )
Spoiler: Windows Registry Editor Version 5.00
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags\AllFolders\Shell]
"FolderType"="NotSpecified"
[HKEY_CURRENT_USER/Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags\AllFolders\Shell\{5C4F28B5-F869-4E84-8E60-F11DB97C5CC7}
"LogicalViewMode"=dword:00000001
"Mode"=dword:00000004
"SortColumn"="prop:System.DateModified"
"SortOrder"="dword:00000001"
Also when win+e it opens home and there are a bunch of things and it slows down, there is a change button to open my computer but it also changes back
When I press saved shortcuts favorites on the left side of the Quick access toolbar, it finds the folder it is in and the view jumps down, and every time I have to scroll up again and again each time I press any favorite.
And when, for example, I need to select a file to upload somewhere, it also does not save the settings and every time hell need yi change the view manually
Please help to sort these problems
Thanks
chat gpt gave this script for PowerShell, not sure if it works
Spoiler: # Specify the view mode and sorting options $viewMode = 1
# Specify the view mode and sorting options
$viewMode = 1 # 1 for Details view
$sortColumn = "System.DateModified"
$sortOrder = 1 # 1 for ascending order, 0 for descending order
# Function to update the view settings for a folder
function UpdateFolderView($folderPath) {
# Path to the desktop.ini file
$desktopIniPath = Join-Path -Path $folderPath -ChildPath "desktop.ini"
# Check if the desktop.ini file exists
if (!(Test-Path -Path $desktopIniPath)) {
# Create the desktop.ini file
New-Item -Path $desktopIniPath -ItemType File | Out-Null
}
# Set the attributes of the desktop.ini file to be hidden and system
(Get-Item -Path $desktopIniPath).Attributes = 'Hidden', 'System'
# Update the content of the desktop.ini file
@"
[ViewState]
Mode=$viewMode
Vid=$sortColumn
Sort=$sortOrder
"@ | Out-File -FilePath $desktopIniPath -Encoding ASCII
}
# Specify the drive letters to target
$driveLetters = 'C', 'F'
# Loop through each drive
foreach ($driveLetter in $driveLetters) {
$drivePath = "$($driveLetter):\"
# Get all folders, including hidden ones, on the drive
$folders = Get-ChildItem -Path $drivePath -Directory -Recurse -Force -ErrorAction SilentlyContinue
# Loop through each folder and update the view settings
foreach ($folder in $folders) {
$folderPath = $folder.FullName
try {
UpdateFolderView -folderPath $folderPath
} catch [System.UnauthorizedAccessException] {
Write-Warning "Skipping folder: $folderPath. Access denied."
} catch {
Write-Warning "An error occurred while processing folder: $folderPath."
}
}
}
Best Windows 11 Folder Settings [Tips & Tricks]
If you wish to keep your PC folder organized, you must check out these Windows 11 folder settings tips and tricks.
windowsreport.com