replace common qcom sources with samsung ones
This commit is contained in:
11
qcom/opensource/mmc-utils/Android.mk
Normal file
11
qcom/opensource/mmc-utils/Android.mk
Normal file
@@ -0,0 +1,11 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_SRC_FILES:= mmc.c mmc_cmds.c
|
||||
LOCAL_MODULE := mmc_utils_internal
|
||||
LOCAL_SHARED_LIBRARIES := libcutils libc
|
||||
LOCAL_C_INCLUDES+= $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/mmc-utils
|
||||
include $(BUILD_EXECUTABLE)
|
46
qcom/opensource/mmc-utils/Makefile
Normal file
46
qcom/opensource/mmc-utils/Makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
CC = gcc
|
||||
AM_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2
|
||||
CFLAGS = -g -O2
|
||||
objects = mmc.o mmc_cmds.o
|
||||
|
||||
CHECKFLAGS= -Wall -Werror -Wuninitialized -Wundef
|
||||
|
||||
DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
|
||||
INSTALL = install
|
||||
prefix ?= /usr/local
|
||||
bindir = $(prefix)/bin
|
||||
LIBS=
|
||||
RESTORE_LIBS=
|
||||
|
||||
progs = mmc
|
||||
|
||||
# make C=1 to enable sparse
|
||||
ifdef C
|
||||
check = sparse $(CHECKFLAGS)
|
||||
endif
|
||||
|
||||
all: $(progs) manpages
|
||||
|
||||
.c.o:
|
||||
ifdef C
|
||||
$(check) $<
|
||||
endif
|
||||
$(CC) $(CHECKFLAGS) $(AM_CFLAGS) $(DEPFLAGS) $(CFLAGS) -c $<
|
||||
|
||||
mmc: $(objects)
|
||||
$(CC) $(CFLAGS) -o $@ $(objects) $(LDFLAGS) $(LIBS)
|
||||
|
||||
manpages:
|
||||
cd man && make
|
||||
|
||||
install-man:
|
||||
cd man && make install
|
||||
|
||||
clean:
|
||||
rm -f $(progs) $(objects)
|
||||
cd man && make clean
|
||||
|
||||
install: $(progs) install-man
|
||||
$(INSTALL) -m755 -d $(DESTDIR)$(bindir)
|
||||
$(INSTALL) $(progs) $(DESTDIR)$(bindir)
|
12
qcom/opensource/mmc-utils/etc/Android.bp
Normal file
12
qcom/opensource/mmc-utils/etc/Android.bp
Normal file
@@ -0,0 +1,12 @@
|
||||
prebuilt_etc {
|
||||
name: "init.qti.ufs.rc",
|
||||
src: "init.qti.ufs.rc",
|
||||
vendor: true,
|
||||
sub_dir: "init/hw",
|
||||
}
|
||||
|
||||
sh_binary {
|
||||
name: "init.qti.ufs.debug.sh",
|
||||
src: "init.qti.ufs.debug.sh",
|
||||
vendor: true,
|
||||
}
|
54
qcom/opensource/mmc-utils/etc/init.qti.ufs.debug.sh
Normal file
54
qcom/opensource/mmc-utils/etc/init.qti.ufs.debug.sh
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/vendor/bin/sh
|
||||
# Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
# * Neither the name of The Linux Foundation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# Enable various ufs ftrace debugging events
|
||||
tracefs=/sys/kernel/tracing
|
||||
ufs_node=$(ls /sys/bus/platform/devices/ | grep ufshc)
|
||||
dbg=`cat /sys/bus/platform/devices/$ufs_node/qcom/dbg_state`
|
||||
|
||||
if [ -d $tracefs -a "$dbg" = 1 ]; then
|
||||
mkdir $tracefs/instances/ufs
|
||||
ufsevent=$tracefs/instances/ufs/set_event
|
||||
|
||||
echo ufshcd_clk_gating > $ufsevent
|
||||
echo ufshcd_clk_scaling >> $ufsevent
|
||||
echo ufshcd_runtime_suspend >> $ufsevent
|
||||
echo ufshcd_runtime_resume >> $ufsevent
|
||||
echo ufshcd_system_suspend >> $ufsevent
|
||||
echo ufshcd_system_resume >> $ufsevent
|
||||
echo ufshcd_command >> $ufsevent
|
||||
|
||||
# scsi
|
||||
echo dispatch_cmd_start >> $ufsevent
|
||||
echo scsi_dispatch_cmd_start >> $ufsevent
|
||||
echo scsi_dispatch_cmd_error >> $ufsevent
|
||||
echo scsi_dispatch_cmd_done >> $ufsevent
|
||||
echo scsi_dispatch_cmd_timeout >> $ufsevent
|
||||
fi
|
||||
|
30
qcom/opensource/mmc-utils/etc/init.qti.ufs.rc
Normal file
30
qcom/opensource/mmc-utils/etc/init.qti.ufs.rc
Normal file
@@ -0,0 +1,30 @@
|
||||
# Copyright (c) 2011-2016, 2018-2020 The Linux Foundation. All rights reserved.
|
||||
# #
|
||||
# # Redistribution and use in source and binary forms, with or without
|
||||
# # modification, are permitted provided that the following conditions are
|
||||
# # met:
|
||||
# # * Redistributions of source code must retain the above copyright
|
||||
# # notice, this list of conditions and the following disclaimer.
|
||||
# # * Redistributions in binary form must reproduce the above
|
||||
# # copyright notice, this list of conditions and the following
|
||||
# # disclaimer in the documentation and/or other materials provided
|
||||
# # with the distribution.
|
||||
# # * Neither the name of The Linux Foundation nor the names of its
|
||||
# # contributors may be used to endorse or promote products derived
|
||||
# # from this software without specific prior written permission.
|
||||
# #
|
||||
# # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
# # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
# # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
# # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
# # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
# # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# on init
|
||||
# exec u:r:vendor-qti-testscripts:s0 -- /vendor/bin/sh /vendor/bin/init.qti.ufs.debug.sh
|
2
qcom/opensource/mmc-utils/man/Makefile
Normal file
2
qcom/opensource/mmc-utils/man/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
clean:
|
373
qcom/opensource/mmc-utils/mmc.c
Normal file
373
qcom/opensource/mmc-utils/mmc.c
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*
|
||||
* (This code is based on btrfs-progs/btrfs.c.)
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mmc_cmds.h"
|
||||
|
||||
#define MMC_VERSION "0.1"
|
||||
|
||||
#define BASIC_HELP 0
|
||||
#define ADVANCED_HELP 1
|
||||
|
||||
typedef int (*CommandFunction)(int argc, char **argv);
|
||||
|
||||
struct Command {
|
||||
CommandFunction func; /* function which implements the command */
|
||||
int nargs; /* if == 999, any number of arguments
|
||||
if >= 0, number of arguments,
|
||||
if < 0, _minimum_ number of arguments */
|
||||
char *verb; /* verb */
|
||||
char *help; /* help lines; from the 2nd line onward they
|
||||
are automatically indented */
|
||||
char *adv_help; /* advanced help message; from the 2nd line
|
||||
onward they are automatically indented */
|
||||
|
||||
/* the following fields are run-time filled by the program */
|
||||
char **cmds; /* array of subcommands */
|
||||
int ncmds; /* number of subcommand */
|
||||
};
|
||||
|
||||
static struct Command commands[] = {
|
||||
/*
|
||||
* avoid short commands different for the case only
|
||||
*/
|
||||
{ do_read_extcsd, -1,
|
||||
"extcsd read", "<device>\n"
|
||||
"Print extcsd data from <device>.",
|
||||
NULL
|
||||
},
|
||||
{ do_writeprotect_get, -1,
|
||||
"writeprotect get", "<device>\n"
|
||||
"Determine the eMMC writeprotect status of <device>.",
|
||||
NULL
|
||||
},
|
||||
{ do_writeprotect_set, -1,
|
||||
"writeprotect set", "<device>\n"
|
||||
"Set the eMMC writeprotect status of <device>.\nThis sets the eMMC to be write-protected until next boot.",
|
||||
NULL
|
||||
},
|
||||
{ do_disable_512B_emulation, -1,
|
||||
"disable 512B emulation", "<device>\n"
|
||||
"Set the eMMC data sector size to 4KB by disabling emulation on\n<device>.",
|
||||
NULL
|
||||
},
|
||||
{ do_write_boot_en, -3,
|
||||
"bootpart enable", "<boot_partition> " "<send_ack> " "<device>\n"
|
||||
"Enable the boot partition for the <device>.\nTo receive acknowledgment of boot from the card set <send_ack>\nto 1, else set it to 0.",
|
||||
NULL
|
||||
},
|
||||
{ do_write_bkops_en, -1,
|
||||
"bkops enable", "<device>\n"
|
||||
"Enable the eMMC BKOPS feature on <device>.\nNOTE! This is a one-time programmable (unreversible) change.",
|
||||
NULL
|
||||
},
|
||||
{ do_hwreset_en, -1,
|
||||
"hwreset enable", "<device>\n"
|
||||
"Permanently enable the eMMC H/W Reset feature on <device>.\nNOTE! This is a one-time programmable (unreversible) change.",
|
||||
NULL
|
||||
},
|
||||
{ do_hwreset_dis, -1,
|
||||
"hwreset disable", "<device>\n"
|
||||
"Permanently disable the eMMC H/W Reset feature on <device>.\nNOTE! This is a one-time programmable (unreversible) change.",
|
||||
NULL
|
||||
},
|
||||
{ do_sanitize, -1,
|
||||
"sanitize", "<device>\n"
|
||||
"Send Sanitize command to the <device>.\nThis will delete the unmapped memory region of the device.",
|
||||
NULL
|
||||
},
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static char *get_prgname(char *programname)
|
||||
{
|
||||
char *np;
|
||||
np = strrchr(programname,'/');
|
||||
if(!np)
|
||||
np = programname;
|
||||
else
|
||||
np++;
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
static void print_help(char *programname, struct Command *cmd, int helptype)
|
||||
{
|
||||
char *pc;
|
||||
|
||||
printf("\t%s %s ", programname, cmd->verb );
|
||||
|
||||
if (helptype == ADVANCED_HELP && cmd->adv_help)
|
||||
for(pc = cmd->adv_help; *pc; pc++){
|
||||
putchar(*pc);
|
||||
if(*pc == '\n')
|
||||
printf("\t\t");
|
||||
}
|
||||
else
|
||||
for(pc = cmd->help; *pc; pc++){
|
||||
putchar(*pc);
|
||||
if(*pc == '\n')
|
||||
printf("\t\t");
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void help(char *np)
|
||||
{
|
||||
struct Command *cp;
|
||||
|
||||
printf("Usage:\n");
|
||||
for( cp = commands; cp->verb; cp++ )
|
||||
print_help(np, cp, BASIC_HELP);
|
||||
|
||||
printf("\n\t%s help|--help|-h\n\t\tShow the help.\n",np);
|
||||
printf("\n\t%s <cmd> --help\n\t\tShow detailed help for a command or subset of commands.\n",np);
|
||||
printf("\n%s\n", MMC_VERSION);
|
||||
}
|
||||
|
||||
static int split_command(char *cmd, char ***commands)
|
||||
{
|
||||
int c, l;
|
||||
char *p, *s;
|
||||
|
||||
for( *commands = 0, l = c = 0, p = s = cmd ; ; p++, l++ ){
|
||||
if ( *p && *p != ' ' )
|
||||
continue;
|
||||
|
||||
/* c + 2 so that we have room for the null */
|
||||
(*commands) = realloc( (*commands), sizeof(char *)*(c + 2));
|
||||
(*commands)[c] = strndup(s, l);
|
||||
c++;
|
||||
l = 0;
|
||||
s = p+1;
|
||||
if( !*p ) break;
|
||||
}
|
||||
|
||||
(*commands)[c] = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
This function checks if the passed command is ambiguous
|
||||
*/
|
||||
static int check_ambiguity(struct Command *cmd, char **argv){
|
||||
int i;
|
||||
struct Command *cp;
|
||||
/* check for ambiguity */
|
||||
for( i = 0 ; i < cmd->ncmds ; i++ ){
|
||||
int match;
|
||||
for( match = 0, cp = commands; cp->verb; cp++ ){
|
||||
int j, skip;
|
||||
char *s1, *s2;
|
||||
|
||||
if( cp->ncmds < i )
|
||||
continue;
|
||||
|
||||
for( skip = 0, j = 0 ; j < i ; j++ )
|
||||
if( strcmp(cmd->cmds[j], cp->cmds[j])){
|
||||
skip=1;
|
||||
break;
|
||||
}
|
||||
if(skip)
|
||||
continue;
|
||||
|
||||
if( !strcmp(cmd->cmds[i], cp->cmds[i]))
|
||||
continue;
|
||||
for(s2 = cp->cmds[i], s1 = argv[i+1];
|
||||
*s1 == *s2 && *s1; s1++, s2++ ) ;
|
||||
if( !*s1 )
|
||||
match++;
|
||||
}
|
||||
if(match){
|
||||
int j;
|
||||
fprintf(stderr, "ERROR: in command '");
|
||||
for( j = 0 ; j <= i ; j++ )
|
||||
fprintf(stderr, "%s%s",j?" ":"", argv[j+1]);
|
||||
fprintf(stderr, "', '%s' is ambiguous\n",argv[j]);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function, compacts the program name and the command in the first
|
||||
* element of the '*av' array
|
||||
*/
|
||||
static int prepare_args(int *ac, char ***av, char *prgname, struct Command *cmd ){
|
||||
|
||||
char **ret;
|
||||
int i;
|
||||
char *newname;
|
||||
|
||||
ret = (char **)malloc(sizeof(char*)*(*ac+1));
|
||||
newname = (char*)malloc(strlen(prgname)+strlen(cmd->verb)+2);
|
||||
if( !ret || !newname ){
|
||||
free(ret);
|
||||
free(newname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret[0] = newname;
|
||||
for(i=0; i < *ac ; i++ )
|
||||
ret[i+1] = (*av)[i];
|
||||
|
||||
strcpy(newname, prgname);
|
||||
strcat(newname, " ");
|
||||
strcat(newname, cmd->verb);
|
||||
|
||||
(*ac)++;
|
||||
*av = ret;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This function performs the following jobs:
|
||||
- show the help if '--help' or 'help' or '-h' are passed
|
||||
- verify that a command is not ambiguous, otherwise show which
|
||||
part of the command is ambiguous
|
||||
- if after a (even partial) command there is '--help' show detailed help
|
||||
for all the matching commands
|
||||
- if the command doesn't match show an error
|
||||
- finally, if a command matches, they return which command matched and
|
||||
the arguments
|
||||
|
||||
The function return 0 in case of help is requested; <0 in case
|
||||
of uncorrect command; >0 in case of matching commands
|
||||
argc, argv are the arg-counter and arg-vector (input)
|
||||
*nargs_ is the number of the arguments after the command (output)
|
||||
**cmd_ is the invoked command (output)
|
||||
***args_ are the arguments after the command
|
||||
|
||||
*/
|
||||
static int parse_args(int argc, char **argv,
|
||||
CommandFunction *func_,
|
||||
int *nargs_, char **cmd_, char ***args_ )
|
||||
{
|
||||
struct Command *cp;
|
||||
struct Command *matchcmd=0;
|
||||
char *prgname = get_prgname(argv[0]);
|
||||
int i=0, helprequested=0;
|
||||
|
||||
if( argc < 2 || !strcmp(argv[1], "help") ||
|
||||
!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
|
||||
help(prgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( cp = commands; cp->verb; cp++ )
|
||||
if( !cp->ncmds)
|
||||
cp->ncmds = split_command(cp->verb, &(cp->cmds));
|
||||
|
||||
for( cp = commands; cp->verb; cp++ ){
|
||||
int match;
|
||||
|
||||
if( argc-1 < cp->ncmds )
|
||||
continue;
|
||||
for( match = 1, i = 0 ; i < cp->ncmds ; i++ ){
|
||||
char *s1, *s2;
|
||||
s1 = cp->cmds[i];
|
||||
s2 = argv[i+1];
|
||||
|
||||
for(s2 = cp->cmds[i], s1 = argv[i+1];
|
||||
*s1 == *s2 && *s1;
|
||||
s1++, s2++ ) ;
|
||||
if( *s1 ){
|
||||
match=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If you understand why this code works ...
|
||||
you are a genious !! */
|
||||
if(argc>i+1 && !strcmp(argv[i+1],"--help")){
|
||||
if(!helprequested)
|
||||
printf("Usage:\n");
|
||||
print_help(prgname, cp, ADVANCED_HELP);
|
||||
helprequested=1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!match)
|
||||
continue;
|
||||
|
||||
matchcmd = cp;
|
||||
*nargs_ = argc-matchcmd->ncmds-1;
|
||||
*cmd_ = matchcmd->verb;
|
||||
*args_ = argv+matchcmd->ncmds+1;
|
||||
*func_ = cp->func;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(helprequested){
|
||||
printf("\n%s\n", MMC_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!matchcmd){
|
||||
fprintf( stderr, "ERROR: unknown command '%s'\n",argv[1]);
|
||||
help(prgname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(check_ambiguity(matchcmd, argv))
|
||||
return -2;
|
||||
|
||||
/* check the number of argument */
|
||||
if (matchcmd->nargs < 0 && matchcmd->nargs < -*nargs_ ){
|
||||
fprintf(stderr, "ERROR: '%s' requires minimum %d arg(s)\n",
|
||||
matchcmd->verb, -matchcmd->nargs);
|
||||
return -2;
|
||||
}
|
||||
if(matchcmd->nargs >= 0 && matchcmd->nargs != *nargs_ && matchcmd->nargs != 999){
|
||||
fprintf(stderr, "ERROR: '%s' requires %d arg(s)\n",
|
||||
matchcmd->verb, matchcmd->nargs);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (prepare_args( nargs_, args_, prgname, matchcmd )){
|
||||
fprintf(stderr, "ERROR: not enough memory\\n");
|
||||
return -20;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
int main(int ac, char **av )
|
||||
{
|
||||
char *cmd=0, **args=0;
|
||||
int nargs=0, r;
|
||||
CommandFunction func=0;
|
||||
|
||||
r = parse_args(ac, av, &func, &nargs, &cmd, &args);
|
||||
if( r <= 0 ){
|
||||
/* error or no command to parse*/
|
||||
exit(-r);
|
||||
}
|
||||
|
||||
exit(func(nargs, args));
|
||||
}
|
||||
|
101
qcom/opensource/mmc-utils/mmc.h
Normal file
101
qcom/opensource/mmc-utils/mmc.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*/
|
||||
|
||||
#include <asm-generic/int-ll64.h>
|
||||
#include <linux/mmc/ioctl.h>
|
||||
#include <linux/major.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define CHECK(expr, msg, err_stmt) { if (expr) { fprintf(stderr, msg); err_stmt; } }
|
||||
|
||||
/* From kernel linux/mmc/mmc.h */
|
||||
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
|
||||
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
|
||||
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
|
||||
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
#define EXT_CSD_S_CMD_SET 504
|
||||
#define EXT_CSD_HPI_FEATURE 503
|
||||
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
|
||||
#define EXT_CSD_BOOT_INFO 228 /* R/W */
|
||||
#define EXT_CSD_PART_SWITCH_TIME 199
|
||||
#define EXT_CSD_BOOT_CFG 179
|
||||
#define EXT_CSD_PART_CONFIG 179
|
||||
#define EXT_CSD_BOOT_WP 173
|
||||
#define EXT_CSD_WR_REL_PARAM 166
|
||||
#define EXT_CSD_SANITIZE_START 165
|
||||
#define EXT_CSD_BKOPS_EN 163 /* R/W */
|
||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||
#define EXT_CSD_NATIVE_SECTOR_SIZE 63 /* R */
|
||||
#define EXT_CSD_USE_NATIVE_SECTOR 62 /* R/W */
|
||||
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
|
||||
|
||||
/*
|
||||
* WR_REL_PARAM field definitions
|
||||
*/
|
||||
#define HS_CTRL_REL (1<<0)
|
||||
#define EN_REL_WR (1<<2)
|
||||
|
||||
/*
|
||||
* BKOPS_EN field definition
|
||||
*/
|
||||
#define BKOPS_ENABLE (1<<0)
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
#define EXT_CSD_HPI_SUPP (1<<0)
|
||||
#define EXT_CSD_HPI_IMPL (1<<1)
|
||||
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
|
||||
#define EXT_CSD_BOOT_INFO_HS_MODE (1<<2)
|
||||
#define EXT_CSD_BOOT_INFO_DDR_DDR (1<<1)
|
||||
#define EXT_CSD_BOOT_INFO_ALT (1<<0)
|
||||
#define EXT_CSD_BOOT_CFG_ACK (1<<6)
|
||||
#define EXT_CSD_BOOT_CFG_EN (0x38)
|
||||
#define EXT_CSD_BOOT_CFG_ACC (0x03)
|
||||
#define EXT_CSD_RST_N_EN_MASK (0x03)
|
||||
#define EXT_CSD_HW_RESET_EN (0x01)
|
||||
#define EXT_CSD_HW_RESET_DIS (0x02)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_BOOT1 (0x2)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_USER_AREA (0x7)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_ACK (0x40)
|
||||
|
||||
/* From kernel linux/mmc/core.h */
|
||||
#define MMC_RSP_PRESENT (1 << 0)
|
||||
#define MMC_RSP_136 (1 << 1) /* 136 bit response */
|
||||
#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
|
||||
#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
|
||||
#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
|
||||
|
||||
#define MMC_CMD_AC (0 << 5)
|
||||
#define MMC_CMD_ADTC (1 << 5)
|
||||
|
||||
#define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */
|
||||
#define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */
|
||||
|
||||
#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1)
|
||||
#define MMC_RSP_SPI_R1B (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY)
|
||||
|
||||
#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
|
||||
#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
|
797
qcom/opensource/mmc-utils/mmc_cmds.c
Normal file
797
qcom/opensource/mmc-utils/mmc_cmds.c
Normal file
@@ -0,0 +1,797 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "mmc.h"
|
||||
#include "mmc_cmds.h"
|
||||
|
||||
int read_extcsd(int fd, __u8 *ext_csd)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mmc_ioc_cmd idata;
|
||||
memset(&idata, 0, sizeof(idata));
|
||||
memset(ext_csd, 0, sizeof(__u8) * 512);
|
||||
idata.write_flag = 0;
|
||||
idata.opcode = MMC_SEND_EXT_CSD;
|
||||
idata.arg = 0;
|
||||
idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
|
||||
idata.blksz = 512;
|
||||
idata.blocks = 1;
|
||||
mmc_ioc_cmd_set_data(idata, ext_csd);
|
||||
|
||||
ret = ioctl(fd, MMC_IOC_CMD, &idata);
|
||||
if (ret)
|
||||
perror("ioctl");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int write_extcsd_value(int fd, __u8 index, __u8 value)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mmc_ioc_cmd idata;
|
||||
|
||||
memset(&idata, 0, sizeof(idata));
|
||||
idata.write_flag = 1;
|
||||
idata.opcode = MMC_SWITCH;
|
||||
idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
||||
(index << 16) |
|
||||
(value << 8) |
|
||||
EXT_CSD_CMD_SET_NORMAL;
|
||||
idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
|
||||
|
||||
ret = ioctl(fd, MMC_IOC_CMD, &idata);
|
||||
if (ret)
|
||||
perror("ioctl");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_writeprotect_status(__u8 *ext_csd)
|
||||
{
|
||||
__u8 reg;
|
||||
__u8 ext_csd_rev = ext_csd[192];
|
||||
|
||||
/* A43: reserved [174:0] */
|
||||
if (ext_csd_rev >= 5) {
|
||||
printf("Boot write protection status registers"
|
||||
" [BOOT_WP_STATUS]: 0x%02x\n", ext_csd[174]);
|
||||
|
||||
reg = ext_csd[EXT_CSD_BOOT_WP];
|
||||
printf("Boot Area Write protection [BOOT_WP]: 0x%02x\n", reg);
|
||||
printf(" Power ro locking: ");
|
||||
if (reg & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
|
||||
printf("not possible\n");
|
||||
else
|
||||
printf("possible\n");
|
||||
|
||||
printf(" Permanent ro locking: ");
|
||||
if (reg & EXT_CSD_BOOT_WP_B_PERM_WP_DIS)
|
||||
printf("not possible\n");
|
||||
else
|
||||
printf("possible\n");
|
||||
|
||||
printf(" ro lock status: ");
|
||||
if (reg & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
|
||||
printf("locked until next power on\n");
|
||||
else if (reg & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
|
||||
printf("locked permanently\n");
|
||||
else
|
||||
printf("not locked\n");
|
||||
}
|
||||
}
|
||||
|
||||
int do_writeprotect_get(int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512];
|
||||
int fd, ret;
|
||||
char *device;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc writeprotect get </path/to/mmcblkX>\n",
|
||||
exit(1));
|
||||
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_writeprotect_status(ext_csd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_writeprotect_set(int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512], value;
|
||||
int fd, ret;
|
||||
char *device;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc writeprotect set </path/to/mmcblkX>\n",
|
||||
exit(1));
|
||||
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
value = ext_csd[EXT_CSD_BOOT_WP] |
|
||||
EXT_CSD_BOOT_WP_B_PWR_WP_EN;
|
||||
ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not write 0x%02x to "
|
||||
"EXT_CSD[%d] in %s\n",
|
||||
value, EXT_CSD_BOOT_WP, device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_disable_512B_emulation(int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512], native_sector_size, data_sector_size, wr_rel_param;
|
||||
int fd, ret;
|
||||
char *device;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc disable 512B emulation </path/to/mmcblkX>\n", exit(1));
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wr_rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
|
||||
native_sector_size = ext_csd[EXT_CSD_NATIVE_SECTOR_SIZE];
|
||||
data_sector_size = ext_csd[EXT_CSD_DATA_SECTOR_SIZE];
|
||||
|
||||
if (native_sector_size && !data_sector_size &&
|
||||
(wr_rel_param & EN_REL_WR)) {
|
||||
ret = write_extcsd_value(fd, EXT_CSD_USE_NATIVE_SECTOR, 1);
|
||||
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
|
||||
1, EXT_CSD_BOOT_WP, device);
|
||||
exit(1);
|
||||
}
|
||||
printf("MMC disable 512B emulation successful. Now reset the device to switch to 4KB native sector mode.\n");
|
||||
} else if (native_sector_size && data_sector_size) {
|
||||
printf("MMC 512B emulation mode is already disabled; doing nothing.\n");
|
||||
} else {
|
||||
printf("MMC does not support disabling 512B emulation mode.\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_write_boot_en(int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512];
|
||||
__u8 value = 0;
|
||||
int fd, ret;
|
||||
char *device;
|
||||
int boot_area, send_ack;
|
||||
|
||||
CHECK(nargs != 4, "Usage: mmc bootpart enable <partition_number> "
|
||||
"<send_ack> </path/to/mmcblkX>\n", exit(1));
|
||||
|
||||
/*
|
||||
* If <send_ack> is 1, the device will send acknowledgment
|
||||
* pattern "010" to the host when boot operation begins.
|
||||
* If <send_ack> is 0, it won't.
|
||||
*/
|
||||
boot_area = strtol(argv[1], NULL, 10);
|
||||
send_ack = strtol(argv[2], NULL, 10);
|
||||
device = argv[3];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
value = ext_csd[EXT_CSD_PART_CONFIG];
|
||||
|
||||
switch (boot_area) {
|
||||
case EXT_CSD_PART_CONFIG_ACC_BOOT0:
|
||||
value |= (1 << 3);
|
||||
value &= ~(3 << 4);
|
||||
break;
|
||||
case EXT_CSD_PART_CONFIG_ACC_BOOT1:
|
||||
value |= (1 << 4);
|
||||
value &= ~(1 << 3);
|
||||
value &= ~(1 << 5);
|
||||
break;
|
||||
case EXT_CSD_PART_CONFIG_ACC_USER_AREA:
|
||||
value |= (boot_area << 3);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Cannot enable the boot area\n");
|
||||
exit(1);
|
||||
}
|
||||
if (send_ack)
|
||||
value |= EXT_CSD_PART_CONFIG_ACC_ACK;
|
||||
else
|
||||
value &= ~EXT_CSD_PART_CONFIG_ACC_ACK;
|
||||
|
||||
ret = write_extcsd_value(fd, EXT_CSD_PART_CONFIG, value);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not write 0x%02x to "
|
||||
"EXT_CSD[%d] in %s\n",
|
||||
value, EXT_CSD_PART_CONFIG, device);
|
||||
exit(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_hwreset(int value, int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512];
|
||||
int fd, ret;
|
||||
char *device;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc hwreset enable </path/to/mmcblkX>\n",
|
||||
exit(1));
|
||||
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((ext_csd[EXT_CSD_RST_N_FUNCTION] & EXT_CSD_RST_N_EN_MASK) ==
|
||||
EXT_CSD_HW_RESET_EN) {
|
||||
fprintf(stderr,
|
||||
"H/W Reset is already permanently enabled on %s\n",
|
||||
device);
|
||||
exit(1);
|
||||
}
|
||||
if ((ext_csd[EXT_CSD_RST_N_FUNCTION] & EXT_CSD_RST_N_EN_MASK) ==
|
||||
EXT_CSD_HW_RESET_DIS) {
|
||||
fprintf(stderr,
|
||||
"H/W Reset is already permanently disabled on %s\n",
|
||||
device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = write_extcsd_value(fd, EXT_CSD_RST_N_FUNCTION, value);
|
||||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"Could not write 0x%02x to EXT_CSD[%d] in %s\n",
|
||||
value, EXT_CSD_RST_N_FUNCTION, device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_hwreset_en(int nargs, char **argv)
|
||||
{
|
||||
return do_hwreset(EXT_CSD_HW_RESET_EN, nargs, argv);
|
||||
}
|
||||
|
||||
int do_hwreset_dis(int nargs, char **argv)
|
||||
{
|
||||
return do_hwreset(EXT_CSD_HW_RESET_DIS, nargs, argv);
|
||||
}
|
||||
|
||||
int do_write_bkops_en(int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512], value = 0;
|
||||
int fd, ret;
|
||||
char *device;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc bkops enable </path/to/mmcblkX>\n",
|
||||
exit(1));
|
||||
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
|
||||
fprintf(stderr, "%s doesn't support BKOPS\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_ENABLE);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
|
||||
value, EXT_CSD_BKOPS_EN, device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_read_extcsd(int nargs, char **argv)
|
||||
{
|
||||
__u8 ext_csd[512], ext_csd_rev, reg;
|
||||
int fd, ret;
|
||||
char *device;
|
||||
const char *str;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc extcsd read </path/to/mmcblkX>\n",
|
||||
exit(1));
|
||||
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read_extcsd(fd, ext_csd);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ext_csd_rev = ext_csd[192];
|
||||
|
||||
switch (ext_csd_rev) {
|
||||
case 6:
|
||||
str = "4.5";
|
||||
break;
|
||||
case 5:
|
||||
str = "4.41";
|
||||
break;
|
||||
case 3:
|
||||
str = "4.3";
|
||||
break;
|
||||
case 2:
|
||||
str = "4.2";
|
||||
break;
|
||||
case 1:
|
||||
str = "4.1";
|
||||
break;
|
||||
case 0:
|
||||
str = "4.0";
|
||||
break;
|
||||
default:
|
||||
goto out_free;
|
||||
}
|
||||
printf("=============================================\n");
|
||||
printf(" Extended CSD rev 1.%d (MMC %s)\n", ext_csd_rev, str);
|
||||
printf("=============================================\n\n");
|
||||
|
||||
if (ext_csd_rev < 3)
|
||||
goto out_free; /* No ext_csd */
|
||||
|
||||
/* Parse the Extended CSD registers.
|
||||
* Reserved bit should be read as "0" in case of spec older
|
||||
* than A441.
|
||||
*/
|
||||
reg = ext_csd[EXT_CSD_S_CMD_SET];
|
||||
printf("Card Supported Command sets [S_CMD_SET: 0x%02x]\n", reg);
|
||||
if (!reg)
|
||||
printf(" - Standard MMC command sets\n");
|
||||
|
||||
reg = ext_csd[EXT_CSD_HPI_FEATURE];
|
||||
printf("HPI Features [HPI_FEATURE: 0x%02x]: ", reg);
|
||||
if (reg & EXT_CSD_HPI_SUPP) {
|
||||
if (reg & EXT_CSD_HPI_IMPL)
|
||||
printf("implementation based on CMD12\n");
|
||||
else
|
||||
printf("implementation based on CMD13\n");
|
||||
}
|
||||
|
||||
printf("Background operations support [BKOPS_SUPPORT: 0x%02x]\n",
|
||||
ext_csd[502]);
|
||||
|
||||
if (ext_csd_rev >= 6) {
|
||||
printf("Max Packet Read Cmd [MAX_PACKED_READS: 0x%02x]\n",
|
||||
ext_csd[501]);
|
||||
printf("Max Packet Write Cmd [MAX_PACKED_WRITES: 0x%02x]\n",
|
||||
ext_csd[500]);
|
||||
printf("Data TAG support [DATA_TAG_SUPPORT: 0x%02x]\n",
|
||||
ext_csd[499]);
|
||||
|
||||
printf("Data TAG Unit Size [TAG_UNIT_SIZE: 0x%02x]\n",
|
||||
ext_csd[498]);
|
||||
printf("Tag Resources Size [TAG_RES_SIZE: 0x%02x]\n",
|
||||
ext_csd[497]);
|
||||
printf("Context Management Capabilities"
|
||||
" [CONTEXT_CAPABILITIES: 0x%02x]\n", ext_csd[496]);
|
||||
printf("Large Unit Size [LARGE_UNIT_SIZE_M1: 0x%02x]\n",
|
||||
ext_csd[495]);
|
||||
printf("Extended partition attribute support"
|
||||
" [EXT_SUPPORT: 0x%02x]\n", ext_csd[494]);
|
||||
printf("Generic CMD6 Timer [GENERIC_CMD6_TIME: 0x%02x]\n",
|
||||
ext_csd[248]);
|
||||
printf("Power off notification [POWER_OFF_LONG_TIME: 0x%02x]\n",
|
||||
ext_csd[247]);
|
||||
printf("Cache Size [CACHE_SIZE] is %d KiB\n",
|
||||
ext_csd[249] << 0 | (ext_csd[250] << 8) |
|
||||
(ext_csd[251] << 16) | (ext_csd[252] << 24));
|
||||
}
|
||||
|
||||
/* A441: Reserved [501:247]
|
||||
A43: reserved [246:229] */
|
||||
if (ext_csd_rev >= 5) {
|
||||
printf("Background operations status"
|
||||
" [BKOPS_STATUS: 0x%02x]\n", ext_csd[246]);
|
||||
|
||||
/* CORRECTLY_PRG_SECTORS_NUM [245:242] TODO */
|
||||
|
||||
printf("1st Initialisation Time after programmed sector"
|
||||
" [INI_TIMEOUT_AP: 0x%02x]\n", ext_csd[241]);
|
||||
|
||||
/* A441: reserved [240] */
|
||||
printf("Power class for 52MHz, DDR at 3.6V"
|
||||
" [PWR_CL_DDR_52_360: 0x%02x]\n", ext_csd[239]);
|
||||
printf("Power class for 52MHz, DDR at 1.95V"
|
||||
" [PWR_CL_DDR_52_195: 0x%02x]\n", ext_csd[238]);
|
||||
|
||||
/* A441: reserved [237-236] */
|
||||
|
||||
if (ext_csd_rev >= 6) {
|
||||
printf("Power class for 200MHz at 3.6V"
|
||||
" [PWR_CL_200_360: 0x%02x]\n", ext_csd[237]);
|
||||
printf("Power class for 200MHz, at 1.95V"
|
||||
" [PWR_CL_200_195: 0x%02x]\n", ext_csd[236]);
|
||||
}
|
||||
printf("Minimum Performance for 8bit at 52MHz in DDR mode:\n");
|
||||
printf(" [MIN_PERF_DDR_W_8_52: 0x%02x]\n", ext_csd[235]);
|
||||
printf(" [MIN_PERF_DDR_R_8_52: 0x%02x]\n", ext_csd[234]);
|
||||
/* A441: reserved [233] */
|
||||
printf("TRIM Multiplier [TRIM_MULT: 0x%02x]\n", ext_csd[232]);
|
||||
printf("Secure Feature support [SEC_FEATURE_SUPPORT: 0x%02x]\n",
|
||||
ext_csd[231]);
|
||||
}
|
||||
if (ext_csd_rev == 5) { /* Obsolete in 4.5 */
|
||||
printf("Secure Erase Multiplier [SEC_ERASE_MULT: 0x%02x]\n",
|
||||
ext_csd[230]);
|
||||
printf("Secure TRIM Multiplier [SEC_TRIM_MULT: 0x%02x]\n",
|
||||
ext_csd[229]);
|
||||
}
|
||||
reg = ext_csd[EXT_CSD_BOOT_INFO];
|
||||
printf("Boot Information [BOOT_INFO: 0x%02x]\n", reg);
|
||||
if (reg & EXT_CSD_BOOT_INFO_ALT)
|
||||
printf(" Device supports alternative boot method\n");
|
||||
if (reg & EXT_CSD_BOOT_INFO_DDR_DDR)
|
||||
printf(" Device supports dual data rate during boot\n");
|
||||
if (reg & EXT_CSD_BOOT_INFO_HS_MODE)
|
||||
printf(" Device supports high speed timing during boot\n");
|
||||
|
||||
/* A441/A43: reserved [227] */
|
||||
printf("Boot partition size [BOOT_SIZE_MULTI: 0x%02x]\n", ext_csd[226]);
|
||||
printf("Access size [ACC_SIZE: 0x%02x]\n", ext_csd[225]);
|
||||
printf("High-capacity erase unit size [HC_ERASE_GRP_SIZE: 0x%02x]\n",
|
||||
ext_csd[224]);
|
||||
printf("High-capacity erase timeout [ERASE_TIMEOUT_MULT: 0x%02x]\n",
|
||||
ext_csd[223]);
|
||||
printf("Reliable write sector count [REL_WR_SEC_C: 0x%02x]\n",
|
||||
ext_csd[222]);
|
||||
printf("High-capacity W protect group size [HC_WP_GRP_SIZE: 0x%02x]\n",
|
||||
ext_csd[221]);
|
||||
printf("Sleep current (VCC) [S_C_VCC: 0x%02x]\n", ext_csd[220]);
|
||||
printf("Sleep current (VCCQ) [S_C_VCCQ: 0x%02x]\n", ext_csd[219]);
|
||||
/* A441/A43: reserved [218] */
|
||||
printf("Sleep/awake timeout [S_A_TIMEOUT: 0x%02x]\n", ext_csd[217]);
|
||||
/* A441/A43: reserved [216] */
|
||||
printf("Sector Count [SEC_COUNT: 0x%08x]\n", (ext_csd[215] << 24) |
|
||||
(ext_csd[214] << 16) | (ext_csd[213] << 8) |
|
||||
ext_csd[212]);
|
||||
/* A441/A43: reserved [211] */
|
||||
printf("Minimum Write Performance for 8bit:\n");
|
||||
printf(" [MIN_PERF_W_8_52: 0x%02x]\n", ext_csd[210]);
|
||||
printf(" [MIN_PERF_R_8_52: 0x%02x]\n", ext_csd[209]);
|
||||
printf(" [MIN_PERF_W_8_26_4_52: 0x%02x]\n", ext_csd[208]);
|
||||
printf(" [MIN_PERF_R_8_26_4_52: 0x%02x]\n", ext_csd[207]);
|
||||
printf("Minimum Write Performance for 4bit:\n");
|
||||
printf(" [MIN_PERF_W_4_26: 0x%02x]\n", ext_csd[206]);
|
||||
printf(" [MIN_PERF_R_4_26: 0x%02x]\n", ext_csd[205]);
|
||||
/* A441/A43: reserved [204] */
|
||||
printf("Power classes registers:\n");
|
||||
printf(" [PWR_CL_26_360: 0x%02x]\n", ext_csd[203]);
|
||||
printf(" [PWR_CL_52_360: 0x%02x]\n", ext_csd[202]);
|
||||
printf(" [PWR_CL_26_195: 0x%02x]\n", ext_csd[201]);
|
||||
printf(" [PWR_CL_52_195: 0x%02x]\n", ext_csd[200]);
|
||||
|
||||
/* A43: reserved [199:198] */
|
||||
if (ext_csd_rev >= 5) {
|
||||
printf("Partition switching timing "
|
||||
"[PARTITION_SWITCH_TIME: 0x%02x]\n", ext_csd[199]);
|
||||
printf("Out-of-interrupt busy timing"
|
||||
" [OUT_OF_INTERRUPT_TIME: 0x%02x]\n", ext_csd[198]);
|
||||
}
|
||||
|
||||
/* A441/A43: reserved [197] [195] [193] [190] [188]
|
||||
* [186] [184] [182] [180] [176] */
|
||||
|
||||
if (ext_csd_rev >= 6)
|
||||
printf("I/O Driver Strength [DRIVER_STRENGTH: 0x%02x]\n",
|
||||
ext_csd[197]);
|
||||
|
||||
printf("Card Type [CARD_TYPE: 0x%02x]\n", ext_csd[196]);
|
||||
/* DEVICE_TYPE in A45 */
|
||||
switch (reg) {
|
||||
case 5:
|
||||
printf("HS200 Single Data Rate eMMC @200MHz 1.2VI/O\n");
|
||||
break;
|
||||
case 4:
|
||||
printf("HS200 Single Data Rate eMMC @200MHz 1.8VI/O\n");
|
||||
break;
|
||||
case 3:
|
||||
printf("HS Dual Data Rate eMMC @52MHz 1.2VI/O\n");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
printf("HS Dual Data Rate eMMC @52MHz 1.8V or 3VI/O\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("HS eMMC @52MHz - at rated device voltage(s)\n");
|
||||
break;
|
||||
case 0:
|
||||
printf("HS eMMC @26MHz - at rated device voltage(s)\n");
|
||||
break;
|
||||
}
|
||||
printf("CSD structure version [CSD_STRUCTURE: 0x%02x]\n", ext_csd[194]);
|
||||
/* ext_csd_rev = ext_csd[192] (already done!!!) */
|
||||
printf("Command set [CMD_SET: 0x%02x]\n", ext_csd[191]);
|
||||
printf("Command set revision [CMD_SET_REV: 0x%02x]\n", ext_csd[189]);
|
||||
printf("Power class [POWER_CLASS: 0x%02x]\n", ext_csd[187]);
|
||||
printf("High-speed interface timing [HS_TIMING: 0x%02x]\n",
|
||||
ext_csd[185]);
|
||||
/* bus_width: ext_csd[183] not readable */
|
||||
printf("Erased memory content [ERASED_MEM_CONT: 0x%02x]\n",
|
||||
ext_csd[181]);
|
||||
reg = ext_csd[EXT_CSD_BOOT_CFG];
|
||||
printf("Boot configuration bytes [PARTITION_CONFIG: 0x%02x]\n", reg);
|
||||
switch (reg & EXT_CSD_BOOT_CFG_EN) {
|
||||
case 0x0:
|
||||
printf(" Not boot enable\n");
|
||||
break;
|
||||
case 0x1:
|
||||
printf(" Boot Partition 1 enabled\n");
|
||||
break;
|
||||
case 0x2:
|
||||
printf(" Boot Partition 2 enabled\n");
|
||||
break;
|
||||
case 0x7:
|
||||
printf(" User Area Enabled for boot\n");
|
||||
break;
|
||||
}
|
||||
switch (reg & EXT_CSD_BOOT_CFG_ACC) {
|
||||
case 0x0:
|
||||
printf(" No access to boot partition\n");
|
||||
break;
|
||||
case 0x1:
|
||||
printf(" R/W Boot Partition 1\n");
|
||||
break;
|
||||
case 0x2:
|
||||
printf(" R/W Boot Partition 2\n");
|
||||
break;
|
||||
default:
|
||||
printf(" Access to General Purpuse partition %d\n",
|
||||
(reg & EXT_CSD_BOOT_CFG_ACC) - 3);
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Boot config protection [BOOT_CONFIG_PROT: 0x%02x]\n",
|
||||
ext_csd[178]);
|
||||
printf("Boot bus Conditions [BOOT_BUS_CONDITIONS: 0x%02x]\n",
|
||||
ext_csd[177]);
|
||||
printf("High-density erase group definition"
|
||||
" [ERASE_GROUP_DEF: 0x%02x]\n", ext_csd[175]);
|
||||
|
||||
print_writeprotect_status(ext_csd);
|
||||
|
||||
if (ext_csd_rev >= 5) {
|
||||
/* A441]: reserved [172] */
|
||||
printf("User area write protection register"
|
||||
" [USER_WP]: 0x%02x\n", ext_csd[171]);
|
||||
/* A441]: reserved [170] */
|
||||
printf("FW configuration [FW_CONFIG]: 0x%02x\n", ext_csd[169]);
|
||||
printf("RPMB Size [RPMB_SIZE_MULT]: 0x%02x\n", ext_csd[168]);
|
||||
printf("Write reliability setting register"
|
||||
" [WR_REL_SET]: 0x%02x\n", ext_csd[167]);
|
||||
printf("Write reliability parameter register"
|
||||
" [WR_REL_PARAM]: 0x%02x\n", ext_csd[166]);
|
||||
/* sanitize_start ext_csd[165]]: not readable
|
||||
* bkops_start ext_csd[164]]: only writable */
|
||||
printf("Enable background operations handshake"
|
||||
" [BKOPS_EN]: 0x%02x\n", ext_csd[163]);
|
||||
printf("H/W reset function"
|
||||
" [RST_N_FUNCTION]: 0x%02x\n", ext_csd[162]);
|
||||
printf("HPI management [HPI_MGMT]: 0x%02x\n", ext_csd[161]);
|
||||
reg = ext_csd[160];
|
||||
printf("Partitioning Support [PARTITIONING_SUPPORT]: 0x%02x\n",
|
||||
reg);
|
||||
if (reg & 0x1)
|
||||
printf(" Device support partitioning feature\n");
|
||||
else
|
||||
printf(" Device NOT support partitioning feature\n");
|
||||
if (reg & 0x2)
|
||||
printf(" Device can have enhanced tech.\n");
|
||||
else
|
||||
printf(" Device cannot have enhanced tech.\n");
|
||||
|
||||
printf("Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x%06x\n",
|
||||
(ext_csd[159] << 16) | (ext_csd[158] << 8) |
|
||||
ext_csd[157]);
|
||||
printf("Partitions attribute [PARTITIONS_ATTRIBUTE]: 0x%02x\n",
|
||||
ext_csd[156]);
|
||||
printf("Partitioning Setting"
|
||||
" [PARTITION_SETTING_COMPLETED]: 0x%02x\n",
|
||||
ext_csd[155]);
|
||||
printf("General Purpose Partition Size\n"
|
||||
" [GP_SIZE_MULT_4]: 0x%06x\n", (ext_csd[154] << 16) |
|
||||
(ext_csd[153] << 8) | ext_csd[152]);
|
||||
printf(" [GP_SIZE_MULT_3]: 0x%06x\n", (ext_csd[151] << 16) |
|
||||
(ext_csd[150] << 8) | ext_csd[149]);
|
||||
printf(" [GP_SIZE_MULT_2]: 0x%06x\n", (ext_csd[148] << 16) |
|
||||
(ext_csd[147] << 8) | ext_csd[146]);
|
||||
printf(" [GP_SIZE_MULT_1]: 0x%06x\n", (ext_csd[145] << 16) |
|
||||
(ext_csd[144] << 8) | ext_csd[143]);
|
||||
|
||||
printf("Enhanced User Data Area Size"
|
||||
" [ENH_SIZE_MULT]: 0x%06x\n", (ext_csd[142] << 16) |
|
||||
(ext_csd[141] << 8) | ext_csd[140]);
|
||||
printf("Enhanced User Data Start Address"
|
||||
" [ENH_START_ADDR]: 0x%06x\n", (ext_csd[139] << 16) |
|
||||
(ext_csd[138] << 8) | ext_csd[137]);
|
||||
|
||||
/* A441]: reserved [135] */
|
||||
printf("Bad Block Management mode"
|
||||
" [SEC_BAD_BLK_MGMNT]: 0x%02x\n", ext_csd[134]);
|
||||
/* A441: reserved [133:0] */
|
||||
}
|
||||
/* B45 */
|
||||
if (ext_csd_rev >= 6) {
|
||||
int j;
|
||||
/* tcase_support ext_csd[132] not readable */
|
||||
printf("Periodic Wake-up [PERIODIC_WAKEUP]: 0x%02x\n",
|
||||
ext_csd[131]);
|
||||
printf("Program CID/CSD in DDR mode support"
|
||||
" [PROGRAM_CID_CSD_DDR_SUPPORT]: 0x%02x\n",
|
||||
ext_csd[130]);
|
||||
|
||||
for (j = 127; j >= 64; j--)
|
||||
printf("Vendor Specific Fields"
|
||||
" [VENDOR_SPECIFIC_FIELD[%d]]: 0x%02x\n",
|
||||
j, ext_csd[j]);
|
||||
|
||||
printf("Native sector size [NATIVE_SECTOR_SIZE]: 0x%02x\n",
|
||||
ext_csd[63]);
|
||||
printf("Sector size emulation [USE_NATIVE_SECTOR]: 0x%02x\n",
|
||||
ext_csd[62]);
|
||||
printf("Sector size [DATA_SECTOR_SIZE]: 0x%02x\n", ext_csd[61]);
|
||||
printf("1st initialization after disabling sector"
|
||||
" size emulation [INI_TIMEOUT_EMU]: 0x%02x\n",
|
||||
ext_csd[60]);
|
||||
printf("Class 6 commands control [CLASS_6_CTRL]: 0x%02x\n",
|
||||
ext_csd[59]);
|
||||
printf("Number of addressed group to be Released"
|
||||
"[DYNCAP_NEEDED]: 0x%02x\n", ext_csd[58]);
|
||||
printf("Exception events control"
|
||||
" [EXCEPTION_EVENTS_CTRL]: 0x%04x\n",
|
||||
(ext_csd[57] << 8) | ext_csd[56]);
|
||||
printf("Exception events status"
|
||||
"[EXCEPTION_EVENTS_STATUS]: 0x%04x\n",
|
||||
(ext_csd[55] << 8) | ext_csd[54]);
|
||||
printf("Extended Partitions Attribute"
|
||||
" [EXT_PARTITIONS_ATTRIBUTE]: 0x%04x\n",
|
||||
(ext_csd[53] << 8) | ext_csd[52]);
|
||||
|
||||
for (j = 51; j >= 37; j--)
|
||||
printf("Context configuration"
|
||||
" [CONTEXT_CONF[%d]]: 0x%02x\n", j, ext_csd[j]);
|
||||
|
||||
printf("Packed command status"
|
||||
" [PACKED_COMMAND_STATUS]: 0x%02x\n", ext_csd[36]);
|
||||
printf("Packed command failure index"
|
||||
" [PACKED_FAILURE_INDEX]: 0x%02x\n", ext_csd[35]);
|
||||
printf("Power Off Notification"
|
||||
" [POWER_OFF_NOTIFICATION]: 0x%02x\n", ext_csd[34]);
|
||||
printf("Control to turn the Cache ON/OFF" " [CACHE_CTRL]: 0x%02x\n", ext_csd[33]);
|
||||
/* flush_cache ext_csd[32] not readable */
|
||||
/*Reserved [31:0] */
|
||||
}
|
||||
|
||||
out_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_sanitize(int nargs, char **argv)
|
||||
{
|
||||
int fd, ret;
|
||||
char *device;
|
||||
|
||||
CHECK(nargs != 2, "Usage: mmc sanitize </path/to/mmcblkX>\n",
|
||||
exit(1));
|
||||
|
||||
device = argv[1];
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = write_extcsd_value(fd, EXT_CSD_SANITIZE_START, 1);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
|
||||
1, EXT_CSD_SANITIZE_START, device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
27
qcom/opensource/mmc-utils/mmc_cmds.h
Normal file
27
qcom/opensource/mmc-utils/mmc_cmds.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*/
|
||||
|
||||
/* mmc_cmds.c */
|
||||
int do_read_extcsd(int nargs, char **argv);
|
||||
int do_write_extcsd(int nargs, char **argv);
|
||||
int do_writeprotect_get(int nargs, char **argv);
|
||||
int do_writeprotect_set(int nargs, char **argv);
|
||||
int do_disable_512B_emulation(int nargs, char **argv);
|
||||
int do_write_boot_en(int nargs, char **argv);
|
||||
int do_write_bkops_en(int nargs, char **argv);
|
||||
int do_hwreset_en(int nargs, char **argv);
|
||||
int do_hwreset_dis(int nargs, char **argv);
|
||||
int do_sanitize(int nargs, char **argv);
|
8
qcom/opensource/mmc-utils/vendor_product.mk
Normal file
8
qcom/opensource/mmc-utils/vendor_product.mk
Normal file
@@ -0,0 +1,8 @@
|
||||
# UFS init scripts
|
||||
PRODUCT_PACKAGES += init.qti.ufs.rc
|
||||
|
||||
# additional debugging on userdebug/eng builds
|
||||
ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
|
||||
PRODUCT_PACKAGES += init.qti.ufs.debug.sh
|
||||
endif
|
||||
|
Reference in New Issue
Block a user