From clauflibitFriiDump-0.5.3.1
This commit is contained in:
parent
fe937e7f4b
commit
87b108d6a1
63 changed files with 11067 additions and 26 deletions
105
libfriidump/CMakeLists.txt
Normal file
105
libfriidump/CMakeLists.txt
Normal file
|
@ -0,0 +1,105 @@
|
|||
# Create a library called "Hello" which includes the source file "hello.cxx".
|
||||
# The extension is already found. Any number of sources could be listed here.
|
||||
add_library (
|
||||
friidumplib
|
||||
${libfriidump_type}
|
||||
#SHARED
|
||||
#STATIC
|
||||
|
||||
brickblocker.h
|
||||
brickblocker.c
|
||||
byteorder.h
|
||||
constants.h
|
||||
disc.h
|
||||
disc.c
|
||||
dumper.h
|
||||
dumper.c
|
||||
dvd_drive.h
|
||||
dvd_drive.c
|
||||
hitachi.c
|
||||
ecma-267.h
|
||||
ecma-267.c
|
||||
lite-on.c
|
||||
misc.h
|
||||
misc.c
|
||||
renesas.c
|
||||
rs.h
|
||||
rs.c
|
||||
unscrambler.h
|
||||
unscrambler.c
|
||||
vanilla_2064.c
|
||||
vanilla_2384.c
|
||||
win32compat.h
|
||||
win32compat.c
|
||||
)
|
||||
|
||||
set_target_properties (friidumplib PROPERTIES OUTPUT_NAME "friidump")
|
||||
|
||||
include_directories (
|
||||
${FriiDump_SOURCE_DIR}/libmultihash
|
||||
)
|
||||
|
||||
# Make sure the linker can find the Hello library once it is built.
|
||||
link_directories (
|
||||
${FriiDump_BINARY_DIR}/libmultihash
|
||||
)
|
||||
|
||||
# Link the executable to the Hello library.
|
||||
target_link_libraries (
|
||||
friidumplib
|
||||
|
||||
multihashlib
|
||||
)
|
||||
|
||||
# Before making a release, the LTVERSION string should be modified.
|
||||
# The string is of the form CURRENT:REVISION:AGE.
|
||||
#
|
||||
# CURRENT (C)
|
||||
# The most recent interface number that this library implements.
|
||||
#
|
||||
# REVISION (R)
|
||||
# The implementation number that this library implements.
|
||||
#
|
||||
# AGE (A)
|
||||
# The difference between the newest and oldest interfaces that this
|
||||
# library implements. In other works, the library implements all the
|
||||
# interface numbers in the range from number 'CURRENT - AGE' to
|
||||
# 'CURRENT'.
|
||||
#
|
||||
# This means that:
|
||||
#
|
||||
# - If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
#
|
||||
# - If binary compatibility has been broken (eg removed or changed
|
||||
# interfaces) change to C+1:0:0
|
||||
#
|
||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||
#
|
||||
#set_target_properties (friidumplib PROPERTIES SOVERSION 1.0.0)
|
||||
|
||||
|
||||
# Windows stuff to correctly build DLL or static library
|
||||
#get_target_property (libfriidump_type friidumplib TYPE)
|
||||
if (WIN32)
|
||||
if (libfriidump_type STREQUAL "SHARED")
|
||||
# MESSAGE ("Building libfriidump DLL")
|
||||
ADD_DEFINITIONS (-DFRIIDUMPLIB_BUILD_DLL)
|
||||
set_target_properties (friidumplib PROPERTIES DEFINE_SYMBOL FRIIDUMPLIB_EXPORTS)
|
||||
|
||||
install (
|
||||
TARGETS friidumplib
|
||||
RUNTIME DESTINATION /
|
||||
#ARCHIVE DESTINATION lib
|
||||
)
|
||||
endif (libfriidump_type STREQUAL "SHARED")
|
||||
else (WIN32)
|
||||
# Install stuff, only if a shared library is being built
|
||||
if (libfriidump_type STREQUAL "SHARED")
|
||||
install (
|
||||
TARGETS friidumplib
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib/static
|
||||
)
|
||||
endif (libfriidump_type STREQUAL "SHARED")
|
||||
endif (WIN32)
|
22
libfriidump/brickblocker.c
Normal file
22
libfriidump/brickblocker.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/* wiidevel@stacktic.org */
|
20
libfriidump/brickblocker.h
Normal file
20
libfriidump/brickblocker.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
77
libfriidump/byteorder.h
Normal file
77
libfriidump/byteorder.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
/*************************** BYTE SWAPPING MACROS ***************************/
|
||||
// WORDS_BIGENDIAN is defined by the AC_C_BIGENDIAN autoconf macro, in case. On Windows please (un)define manually.
|
||||
#ifdef WORDS_BIGENDIAN //!< Swapping macros on big endian systems (Where host b. o. = network b. o.)
|
||||
|
||||
/* This machine's order to big endian */
|
||||
#define bo_my2big_16(a) ((u_int16_t)(a))
|
||||
#define bo_my2big_32(a) ((u_int32_t)(a))
|
||||
|
||||
/* This machine's order to little endian */
|
||||
#define bo_my2little_16(a) ( \
|
||||
((((u_int16_t) (a)) & 0x00FF) << 8) + \
|
||||
(((u_int16_t) (a)) >> 8) \
|
||||
)
|
||||
#define bo_my2little_32(a) ( \
|
||||
((((u_int32_t) (a)) & 0x000000FF) << 24) + \
|
||||
((((u_int32_t) (a)) & 0x0000FF00) << 8) + \
|
||||
((((u_int32_t) (a)) & 0x00FF0000) >> 8) + \
|
||||
(((u_int32_t) (a)) >> 24) \
|
||||
)
|
||||
#else //!< Swapping macros on little endian systems
|
||||
/* This machine's order to big endian */
|
||||
#define bo_my2big_16(a) ( \
|
||||
((((u_int16_t) (a)) & 0x00FF) << 8) + \
|
||||
(((u_int16_t) (a)) >> 8) \
|
||||
)
|
||||
#define bo_my2big_32(a) ( \
|
||||
((((u_int32_t) (a)) & 0x000000FF) << 24) + \
|
||||
((((u_int32_t) (a)) & 0x0000FF00) << 8) + \
|
||||
((((u_int32_t) (a)) & 0x00FF0000) >> 8) + \
|
||||
(((u_int32_t) (a)) >> 24) \
|
||||
)
|
||||
|
||||
/* This machine's order to little endian */
|
||||
#define bo_my2little_16(a) ((u_int16_t)(a))
|
||||
#define bo_my2little_32(a) ((u_int32_t)(a))
|
||||
#endif
|
||||
|
||||
/* These will be handy */
|
||||
/* Big endian to this machine's order */
|
||||
#define bo_big2my_16(x) bo_my2big_16(x)
|
||||
#define bo_big2my_32(x) bo_my2big_32(x)
|
||||
|
||||
/* Little endian to this machine's order */
|
||||
#define bo_little2my_16(x) bo_my2little_16(x)
|
||||
#define bo_little2my_32(x) bo_my2little_32(x)
|
||||
|
||||
/* There are the most useful ones */
|
||||
#define my_htons(x) bo_my2big_16(x)
|
||||
#define my_htonl(x) bo_my2big_32(x)
|
||||
#define my_ntohs(x) my_htons(x)
|
||||
#define my_ntohl(x) my_htonl(x)
|
||||
|
||||
/************************ END OF BYTE SWAPPING MACROS ***********************/
|
46
libfriidump/constants.h
Normal file
46
libfriidump/constants.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief Nintendo GameCube/Wii disc geometry constants.
|
||||
*
|
||||
* This file contains constants that describe the general layout of Nintendo GameCube/Wii discs and that can be used throughout the whole program.
|
||||
*/
|
||||
|
||||
#ifndef CONSTANTS_H_INCLUDED
|
||||
#define CONSTANTS_H_INCLUDED
|
||||
|
||||
/*! \brief Size of a scrambled sector */
|
||||
#define RAW_SECTOR_SIZE 2064
|
||||
|
||||
/*! \brief Size of an unscrambled sector */
|
||||
#define SECTOR_SIZE 2048
|
||||
|
||||
/*! \brief Number of sectors in a block */
|
||||
#define SECTORS_PER_BLOCK 16
|
||||
|
||||
/*! \brief Size of a scrambled block */
|
||||
#define RAW_BLOCK_SIZE (RAW_SECTOR_SIZE * SECTORS_PER_BLOCK)
|
||||
|
||||
/*! \brief Size of an unscrambled block */
|
||||
#define BLOCK_SIZE (SECTOR_SIZE * SECTORS_PER_BLOCK)
|
||||
|
||||
#endif
|
1675
libfriidump/disc.c
Normal file
1675
libfriidump/disc.c
Normal file
File diff suppressed because it is too large
Load diff
94
libfriidump/disc.h
Normal file
94
libfriidump/disc.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DISC_H_INCLUDED
|
||||
#define DISC_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
DISC_TYPE_GAMECUBE,
|
||||
DISC_TYPE_WII,
|
||||
DISC_TYPE_WII_DL,
|
||||
DISC_TYPE_DVD
|
||||
} disc_type;
|
||||
|
||||
|
||||
typedef enum {
|
||||
DISC_REGION_PAL,
|
||||
DISC_REGION_NTSC,
|
||||
DISC_REGION_JAPAN,
|
||||
DISC_REGION_AUSTRALIA,
|
||||
DISC_REGION_FRANCE,
|
||||
DISC_REGION_GERMANY,
|
||||
DISC_REGION_ITALY,
|
||||
DISC_REGION_SPAIN,
|
||||
DISC_REGION_PAL_X,
|
||||
DISC_REGION_PAL_Y,
|
||||
DISC_REGION_UNKNOWN
|
||||
} disc_region;
|
||||
|
||||
|
||||
typedef struct disc_s disc;
|
||||
|
||||
|
||||
/* Functions */
|
||||
FRIIDUMPLIB_EXPORT disc *disc_new (char *dvd_device, u_int32_t command);
|
||||
FRIIDUMPLIB_EXPORT bool disc_init (disc *d, u_int32_t forced_type, u_int32_t sectors_no);
|
||||
FRIIDUMPLIB_EXPORT void *disc_destroy (disc *d);
|
||||
FRIIDUMPLIB_EXPORT int disc_read_sector (disc *d, u_int32_t sector_no, u_int8_t **data, u_int8_t **rawdata);
|
||||
FRIIDUMPLIB_EXPORT bool disc_set_read_method (disc *d, int method);
|
||||
FRIIDUMPLIB_EXPORT void disc_set_unscrambling (disc *d, bool unscramble);
|
||||
FRIIDUMPLIB_EXPORT void disc_set_speed (disc *d, u_int32_t speed);
|
||||
FRIIDUMPLIB_EXPORT void disc_set_streaming_speed (disc *d, u_int32_t speed);
|
||||
FRIIDUMPLIB_EXPORT bool disc_stop_unit (disc *d, bool start);
|
||||
FRIIDUMPLIB_EXPORT void init_range (disc *d, u_int32_t sec_disc, u_int32_t sec_mem);
|
||||
|
||||
/* Getters */
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sectors_no (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_layerbreak (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_command (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_method (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_def_method (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sec_disc (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sec_mem (disc *d);
|
||||
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_type (disc *d, disc_type *dt, char **dt_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_gameid (disc *d, char **gid_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_region (disc *d, disc_region *dr, char **dr_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_maker (disc *d, char **m, char **m_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_version (disc *d, u_int8_t *v, char **v_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_title (disc *d, char **t_s);
|
||||
FRIIDUMPLIB_EXPORT bool disc_get_update (disc *d);
|
||||
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_drive_model_string (disc *d);
|
||||
FRIIDUMPLIB_EXPORT bool disc_get_drive_support_status (disc *d);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
439
libfriidump/dumper.c
Normal file
439
libfriidump/dumper.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <multihash.h>
|
||||
#include "constants.h"
|
||||
#include "disc.h"
|
||||
#include "dumper.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
struct dumper_s {
|
||||
disc *dsk;
|
||||
char *outfile_raw;
|
||||
u_int32_t start_sector_raw;
|
||||
FILE *fp_raw;
|
||||
char *outfile_iso;
|
||||
u_int32_t start_sector_iso;
|
||||
FILE *fp_iso;
|
||||
u_int32_t start_sector;
|
||||
bool hashing;
|
||||
bool flushing;
|
||||
|
||||
multihash hash_raw;
|
||||
multihash hash_iso;
|
||||
|
||||
progress_func progress;
|
||||
void *progress_data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tries to open the output file for writing and to find out if it contains valid data so that the dump can continue.
|
||||
* @param dvd
|
||||
* @param outfile
|
||||
* @param[out] fp The file pointer to write to.
|
||||
* @param[out] start_sector The sector to start reading from.
|
||||
* @return true if the dumping can start/continue, false otherwise (for instance if outfile cannot be written to).
|
||||
*/
|
||||
bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume) {
|
||||
bool out;
|
||||
my_off_t filesize;
|
||||
FILE *fp;
|
||||
|
||||
if (!outfile_raw) {
|
||||
/* Raw output disabled */
|
||||
out = true;
|
||||
dmp -> start_sector_raw = -1;
|
||||
my_free (dmp -> outfile_raw);
|
||||
dmp -> outfile_raw = NULL;
|
||||
} else if (dmp -> outfile_raw) {
|
||||
error ("Raw output file already defined");
|
||||
out = false;
|
||||
} else if (!(fp = fopen (outfile_raw, "rb"))) { /** @todo Maybe we could not open file for permission problems */
|
||||
/* Raw output file does not exist, start from scratch */
|
||||
out = true;
|
||||
dmp -> start_sector_raw = 0;
|
||||
my_strdup (dmp -> outfile_raw, outfile_raw);
|
||||
} else if (resume) {
|
||||
/* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
|
||||
my_fseek (fp, 0, SEEK_END);
|
||||
filesize = my_ftell (fp);
|
||||
fclose (fp);
|
||||
out = true;
|
||||
dmp -> start_sector_raw = (u_int32_t) (filesize / RAW_SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
|
||||
debug ("Raw output can restart from sector %u", dmp -> start_sector_raw);
|
||||
my_strdup (dmp -> outfile_raw, outfile_raw);
|
||||
} else {
|
||||
/* Raw output file exists but resume was not requested, error */
|
||||
fclose (fp);
|
||||
error ("Raw output file exists, but resume was not requested.");
|
||||
out = false;
|
||||
dmp -> start_sector_raw = -1;
|
||||
my_free (dmp -> outfile_raw);
|
||||
dmp -> outfile_raw = NULL;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume) {
|
||||
bool out;
|
||||
my_off_t filesize;
|
||||
FILE *fp;
|
||||
|
||||
if (!outfile_iso) {
|
||||
/* Raw output disabled */
|
||||
out = true;
|
||||
dmp -> start_sector_iso = -1;
|
||||
my_free (dmp -> outfile_iso);
|
||||
dmp -> outfile_iso = NULL;
|
||||
} else if (dmp -> outfile_iso) {
|
||||
error ("ISO output file already defined");
|
||||
out = false;
|
||||
} else if (!(fp = fopen (outfile_iso, "rb"))) { /** @todo Maybe we could not open file for permission problems */
|
||||
/* Raw output file does not exist, start from scratch */
|
||||
out = true;
|
||||
dmp -> start_sector_iso = 0;
|
||||
my_strdup (dmp -> outfile_iso, outfile_iso);
|
||||
} else if (resume) {
|
||||
/* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
|
||||
my_fseek (fp, 0, SEEK_END);
|
||||
filesize = my_ftell (fp);
|
||||
fclose (fp);
|
||||
out = true;
|
||||
dmp -> start_sector_iso = (u_int32_t) (filesize / SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
|
||||
debug ("ISO output can restart from sector %u", dmp -> start_sector_iso);
|
||||
my_strdup (dmp -> outfile_iso, outfile_iso);
|
||||
} else {
|
||||
/* Raw output file exists but resume was not requested, error */
|
||||
fclose (fp);
|
||||
error ("ISO output file exists, but resume was not requested.");
|
||||
out = false;
|
||||
dmp -> start_sector_iso = -1;
|
||||
my_free (dmp -> outfile_iso);
|
||||
dmp -> outfile_iso = NULL;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
bool dumper_prepare (dumper *dmp) {
|
||||
bool out;
|
||||
u_int8_t buf[RAW_SECTOR_SIZE];
|
||||
size_t r;
|
||||
u_int32_t i;
|
||||
|
||||
/* Outputting to both files, resume must start from the file with the least sectors. Hopefully they will have the same number of sectors, anyway... */
|
||||
if (dmp -> outfile_raw && dmp -> outfile_iso && dmp -> start_sector_raw != dmp -> start_sector_iso) {
|
||||
if (dmp -> start_sector_raw < dmp -> start_sector_iso)
|
||||
dmp -> start_sector = dmp -> start_sector_raw;
|
||||
else
|
||||
dmp -> start_sector = dmp -> start_sector_iso;
|
||||
} else if (dmp -> outfile_raw) {
|
||||
dmp -> start_sector = dmp -> start_sector_raw;
|
||||
} else if (dmp -> outfile_iso) {
|
||||
dmp -> start_sector = dmp -> start_sector_iso;
|
||||
} else {
|
||||
MY_ASSERT (0);
|
||||
}
|
||||
|
||||
/* Prepare hashes */
|
||||
if (dmp -> hashing) {
|
||||
multihash_init (&(dmp -> hash_raw));
|
||||
multihash_init (&(dmp -> hash_iso));
|
||||
}
|
||||
|
||||
/* Setup raw output file */
|
||||
if (dmp -> outfile_raw) {
|
||||
dmp -> fp_raw = fopen (dmp -> outfile_raw, "a+b");
|
||||
|
||||
if (dmp -> hashing) {
|
||||
debug ("Calculating hashes for pre-existing raw dump data");
|
||||
if (dmp -> start_sector > 0) {
|
||||
for (i = 0; i < dmp -> start_sector && (r = fread (buf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw)) > 0; i++)
|
||||
multihash_update (&(dmp -> hash_raw), buf, RAW_SECTOR_SIZE);
|
||||
MY_ASSERT (r > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now call fseek as file will only be written, from now on */
|
||||
if (my_fseek (dmp -> fp_raw, dmp -> start_sector * RAW_SECTOR_SIZE, SEEK_SET) == 0 &&
|
||||
ftruncate (fileno (dmp -> fp_raw), (int64_t) dmp -> start_sector * RAW_SECTOR_SIZE) == 0) {
|
||||
out = true;
|
||||
debug ("Writing to file \"%s\" in raw format (fseeked() to %lld)", dmp -> outfile_raw, my_ftell (dmp -> fp_raw));
|
||||
} else {
|
||||
out = false;
|
||||
fclose (dmp -> fp_raw);
|
||||
dmp -> fp_raw = NULL;
|
||||
}
|
||||
} else {
|
||||
dmp -> fp_raw = NULL;
|
||||
}
|
||||
|
||||
/* Setup ISO output file */
|
||||
if (dmp -> outfile_iso) {
|
||||
dmp -> fp_iso = fopen (dmp -> outfile_iso, "a+b");
|
||||
|
||||
if (dmp -> hashing) {
|
||||
debug ("Calculating hashes for pre-existing ISO dump data");
|
||||
if (dmp -> start_sector > 0) {
|
||||
for (i = 0; i < dmp -> start_sector && (r = fread (buf, SECTOR_SIZE, 1, dmp -> fp_iso)) > 0; i++)
|
||||
multihash_update (&(dmp -> hash_iso), buf, SECTOR_SIZE);
|
||||
MY_ASSERT (r > 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (my_fseek (dmp -> fp_iso, dmp -> start_sector * SECTOR_SIZE, SEEK_SET) == 0 &&
|
||||
ftruncate (fileno (dmp -> fp_iso), (int64_t) dmp -> start_sector * SECTOR_SIZE) == 0) {
|
||||
out = true;
|
||||
debug ("Writing to file \"%s\" in ISO format (fseeked() to %lld)", dmp -> outfile_iso, my_ftell (dmp -> fp_iso));
|
||||
} else {
|
||||
out = false;
|
||||
fclose (dmp -> fp_iso);
|
||||
dmp -> fp_iso = NULL;
|
||||
}
|
||||
} else {
|
||||
dmp -> fp_iso = NULL;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
int dumper_dump (dumper *dmp, u_int32_t *current_sector) {
|
||||
bool out;
|
||||
u_int8_t *rawbuf, *isobuf;
|
||||
u_int32_t i, sectors_no, last_sector;
|
||||
#ifdef DEBUGaa
|
||||
bool no_unscrambling;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGaa
|
||||
no_unscrambling = dd -> no_unscrambling;
|
||||
if (fp_iso && no_unscrambling) {
|
||||
warning ("Output to ISO format requested, ignoring no_unscrambling!");
|
||||
no_unscrambling = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
sectors_no = disc_get_sectors_no (dmp -> dsk);
|
||||
#if 0
|
||||
if (dd -> start_sector != -1) {
|
||||
if (dd -> start_sector >= sectors_no) {
|
||||
error ("Cannot start dumping from sector %u as the inserted disc only has %u sectors\n", dd -> start_sector, sectors_no);
|
||||
out = false;
|
||||
} else {
|
||||
warning ("Start sector forced to %u\n", dd -> start_sector);
|
||||
ss = dd -> start_sector;
|
||||
|
||||
if (fp_iso)
|
||||
fseek (fp_iso, ss * 2048, SEEK_SET);
|
||||
if (fp_raw)
|
||||
fseek (fp_raw, ss * 2064, SEEK_SET);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (true) {
|
||||
debug ("Starting dump process from sector %u...\n", dmp -> start_sector);
|
||||
|
||||
/* First call to progress function */
|
||||
if (dmp -> progress)
|
||||
dmp -> progress (true, dmp -> start_sector, sectors_no, dmp -> progress_data);
|
||||
|
||||
last_sector=sectors_no-1;
|
||||
|
||||
for (i = dmp -> start_sector, out = true; i < sectors_no && out; i++) {
|
||||
disc_read_sector (dmp -> dsk, i, &isobuf, &rawbuf);
|
||||
|
||||
if (dmp -> fp_raw) {
|
||||
clearerr (dmp -> fp_raw);
|
||||
|
||||
if (!rawbuf) {
|
||||
error ("NULL buffer");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
else fwrite (rawbuf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw);
|
||||
if (ferror (dmp -> fp_raw)) {
|
||||
error ("fwrite() to raw output file failed");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
|
||||
if (dmp -> flushing)
|
||||
fflush (dmp -> fp_raw);
|
||||
|
||||
if (dmp -> hashing && out)
|
||||
multihash_update (&(dmp -> hash_raw), rawbuf, RAW_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if (dmp -> fp_iso) {
|
||||
clearerr (dmp -> fp_iso);
|
||||
|
||||
if (!isobuf) {
|
||||
error ("NULL buffer");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
else fwrite (isobuf, SECTOR_SIZE, 1, dmp -> fp_iso);
|
||||
|
||||
if (ferror (dmp -> fp_iso)) {
|
||||
error ("fwrite() to ISO output file failed");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
|
||||
if (dmp -> flushing)
|
||||
fflush (dmp -> fp_iso);
|
||||
|
||||
if (dmp -> hashing && out)
|
||||
multihash_update (&(dmp -> hash_iso), isobuf, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if ((i % 320 == 0) || (i == last_sector)) { //speedhack
|
||||
if (dmp -> progress)
|
||||
dmp -> progress (false, i + 1, sectors_no, dmp -> progress_data); /* i + 1 'cause sectors range from 0 to N */
|
||||
}
|
||||
}
|
||||
|
||||
if (dmp -> hashing) {
|
||||
multihash_finish (&(dmp -> hash_raw));
|
||||
multihash_finish (&(dmp -> hash_iso));
|
||||
}
|
||||
|
||||
if (dmp -> fp_raw)
|
||||
fclose (dmp -> fp_raw);
|
||||
if (dmp -> fp_iso)
|
||||
fclose (dmp -> fp_iso);
|
||||
if (out) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
dumper *dumper_new (disc *d) {
|
||||
dumper *dmp;
|
||||
|
||||
dmp = (dumper *) malloc (sizeof (dumper));
|
||||
memset (dmp, 0, sizeof (dumper));
|
||||
dmp -> dsk = d;
|
||||
dumper_set_hashing (dmp, true);
|
||||
dumper_set_flushing (dmp, true);
|
||||
|
||||
return (dmp);
|
||||
}
|
||||
|
||||
|
||||
void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data) {
|
||||
dmp -> progress = progress;
|
||||
dmp -> progress_data = progress_data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dumper_set_hashing (dumper *dmp, bool h) {
|
||||
dmp -> hashing = h;
|
||||
debug ("Hashing %s", h ? "enabled" : "disabled");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dumper_set_flushing (dumper *dmp, bool f) {
|
||||
dmp -> flushing = f;
|
||||
debug ("Flushing %s", f ? "enabled" : "disabled");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *dumper_destroy (dumper *dmp) {
|
||||
my_free (dmp -> outfile_raw);
|
||||
my_free (dmp -> outfile_iso);
|
||||
my_free (dmp);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_crc32 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).crc32_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_crc32 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).crc32_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_md4 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).md4_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_md4 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).md4_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_md5 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).md5_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_md5 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).md5_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_ed2k (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).ed2k_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_ed2k (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).ed2k_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_sha1 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).sha1_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_sha1 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).sha1_s);
|
||||
}
|
60
libfriidump/dumper.h
Normal file
60
libfriidump/dumper.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DUMPER_H_INCLUDED
|
||||
#define DUMPER_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct dumper_s dumper;
|
||||
|
||||
typedef void (*progress_func) (bool start, u_int32_t current_sector, u_int32_t total_sectors, void *progress_data);
|
||||
|
||||
FRIIDUMPLIB_EXPORT bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume);
|
||||
FRIIDUMPLIB_EXPORT bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume);
|
||||
FRIIDUMPLIB_EXPORT bool dumper_prepare (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT int dumper_dump (dumper *dmp, u_int32_t *current_sector);
|
||||
FRIIDUMPLIB_EXPORT dumper *dumper_new (disc *d);
|
||||
FRIIDUMPLIB_EXPORT void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data);
|
||||
FRIIDUMPLIB_EXPORT void dumper_set_hashing (dumper *dmp, bool h);
|
||||
FRIIDUMPLIB_EXPORT void dumper_set_flushing (dumper *dmp, bool f);
|
||||
FRIIDUMPLIB_EXPORT void *dumper_destroy (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_crc32 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_crc32 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_md4 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_md4 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_md5 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_md5 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_ed2k (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_ed2k (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_sha1 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_sha1 (dumper *dmp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
755
libfriidump/dvd_drive.c
Normal file
755
libfriidump/dvd_drive.c
Normal file
|
@ -0,0 +1,755 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief A class to send raw MMC commands to a CD/DVD-ROM drive.
|
||||
*
|
||||
* This class can be used to send raw MMC commands to a CD/DVD-ROM drive. It uses own structures and data types to represent the commands, which are
|
||||
* then transformed in the proper OS-dependent structures when the command is executed, achieving portability. Currently Linux and Windows are supported, but
|
||||
* all that is needed to add support to a new OS is a proper <code>dvd_execute_cmd()</code> function, so it should be very easy. I hope that someone can add
|
||||
* compatibility with MacOS X and *BSD: libcdio is a good place to understand how it should be done :). Actally, we could have used libcdio right from the start,
|
||||
* but I didn't want to add a dependency on a library that cannot be easily found in binary format for all the target OS's.
|
||||
*
|
||||
* This file contains code derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/ , which, in turn, derives from work by
|
||||
* a lot of other people. See his page for full details.
|
||||
*/
|
||||
|
||||
#include "rs.h"
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
//#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "dvd_drive.h"
|
||||
#include "disc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <ntddscsi.h>
|
||||
#else
|
||||
#include <linux/cdrom.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*! \brief Timeout for MMC commands.
|
||||
*
|
||||
* This must be expressed in seconds (Windows uses seconds, right?).
|
||||
*/
|
||||
#define MMC_CMD_TIMEOUT 10
|
||||
|
||||
|
||||
/* Imported drive-specific functions */
|
||||
int vanilla_2064_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int vanilla_2384_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int hitachi_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int liteon_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int renesas_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
|
||||
|
||||
/*! \brief A structure that represents a CD/DVD-ROM drive.
|
||||
*/
|
||||
struct dvd_drive_s {
|
||||
/* Device special file */
|
||||
char *device; //!< The path to the drive (i.e.: /dev/something on Unix, x: on Windows).
|
||||
|
||||
/* Data about the drive */
|
||||
char *vendor; //!< The drive vendor.
|
||||
char *prod_id; //!< The drive product ID.
|
||||
char *prod_rev; //!< The drive product revision (Usually firmware version).
|
||||
char *model_string; //!< The above three strings, joined in a single one.
|
||||
u_int32_t def_method;
|
||||
u_int32_t command;
|
||||
|
||||
/* Device-dependent internal memory dump function */
|
||||
/*! The intended area should start where sector data is stored upon a READ command. Here we assume that sectors are
|
||||
* stored one after the other, as heuristics showed it is the case for the Hitachi MN103-based drives, but this model
|
||||
* might be changed in the future, if we get support for other drives.
|
||||
*/
|
||||
dvd_drive_memdump_func memdump; //!< A pointer to a function that is able to dump the drive's internal memory area.
|
||||
bool supported; //!< True if the drive is a supported model, false otherwise.
|
||||
|
||||
|
||||
/* File descriptor & stuff used to access drive */
|
||||
#ifdef WIN32
|
||||
HANDLE fd; //!< The HANDLE to interact with the drive on Windows.
|
||||
#else
|
||||
int fd; //!< The file descriptor to interact with the drive on Unix.
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/** \brief Supported MMC commands.
|
||||
*/
|
||||
enum mmc_commands_e {
|
||||
SPC_INQUIRY = 0x12,
|
||||
MMC_READ_12 = 0xA8,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a structure representing an MMC command.
|
||||
* @param mmc A pointer to the MMC command structure.
|
||||
* @param buf The buffer where results of the MMC command execution provided by the drive should be stored, or NULL if no buffer will be provided.
|
||||
* @param len The length of the buffer (ignored in case buf is NULL).
|
||||
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed, or NULL.
|
||||
*/
|
||||
void dvd_init_command (mmc_command *mmc, u_int8_t *buf, int len, req_sense *sense) {
|
||||
memset (mmc, 0, sizeof (mmc_command));
|
||||
if (buf)
|
||||
memset (buf, 0, len);
|
||||
mmc -> buffer = buf;
|
||||
mmc -> buflen = buf ? len : 0;
|
||||
mmc -> sense = sense;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/* Doc is under the UNIX function */
|
||||
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors) {
|
||||
SCSI_PASS_THROUGH_DIRECT *sptd;
|
||||
unsigned char sptd_sense[sizeof (*sptd) + 18], *sense;
|
||||
DWORD bytes;
|
||||
int out;
|
||||
|
||||
sptd = (SCSI_PASS_THROUGH_DIRECT *) sptd_sense;
|
||||
sense = &sptd_sense[sizeof (*sptd)];
|
||||
|
||||
memset (sptd, 0, sizeof (sptd_sense));
|
||||
memcpy (sptd -> Cdb, mmc -> cmd, sizeof (mmc -> cmd));
|
||||
sptd -> Length = sizeof (SCSI_PASS_THROUGH);
|
||||
sptd -> CdbLength = 12;
|
||||
sptd -> SenseInfoLength = 18;
|
||||
sptd -> DataIn = SCSI_IOCTL_DATA_IN;
|
||||
sptd -> DataBuffer = mmc -> buffer;
|
||||
// Quick hack: Windows hates sptd->DataTransferLength = 1, so we set it to 2 and ignore the second byte.
|
||||
if (mmc -> buflen == 1) // TODO
|
||||
sptd -> DataTransferLength = 2;
|
||||
else
|
||||
sptd -> DataTransferLength = mmc -> buflen;
|
||||
sptd -> TimeOutValue = MMC_CMD_TIMEOUT;
|
||||
sptd -> SenseInfoOffset = sizeof (*sptd);
|
||||
|
||||
//fprintf (stdout,"mmc->cmd[00] = %d \n",mmc->cmd[00]);
|
||||
//Set streaming hack
|
||||
if (mmc->cmd[00]==0xB6) {
|
||||
sptd -> DataIn = SCSI_IOCTL_DATA_OUT;
|
||||
sptd -> DataTransferLength = 28;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl (dvd -> fd, IOCTL_SCSI_PASS_THROUGH_DIRECT, sptd, sizeof (*sptd) + 18, sptd, sizeof (*sptd) + 18, &bytes, NULL) && !ignore_errors) {
|
||||
out = -1; /* Failure */
|
||||
error ("Execution of MMC command failed: %s", strerror (errno));
|
||||
// error ("DeviceIOControl() failed with %d\n", GetLastError());
|
||||
debug ("Command was: ");
|
||||
hex_and_ascii_print ("", mmc -> cmd, sizeof (mmc -> cmd));
|
||||
debug ("Sense data: %02X/%02X/%02X\n", sense[2] & 0x0F, sense[12], sense[13]);
|
||||
} else {
|
||||
out = 0;
|
||||
}
|
||||
|
||||
if (mmc -> sense) {
|
||||
mmc -> sense -> sense_key = sense[2];
|
||||
mmc -> sense -> asc = sense[12];
|
||||
mmc -> sense -> ascq = sense[13];
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Executes an MMC command.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param mmc The command to be executed.
|
||||
* @param ignore_errors If set to true, no error will be printed if the command fails.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors) {
|
||||
int out;
|
||||
struct cdrom_generic_command cgc;
|
||||
struct request_sense sense;
|
||||
|
||||
#if 0
|
||||
debug ("Executing MMC command: ");
|
||||
hex_and_ascii_print ("", mmc -> cmd, sizeof (mmc -> cmd));
|
||||
#endif
|
||||
|
||||
/* Init Linux-format MMC command */
|
||||
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
|
||||
memcpy (cgc.cmd, mmc -> cmd, sizeof (mmc -> cmd));
|
||||
cgc.buffer = (unsigned char *) mmc -> buffer;
|
||||
cgc.buflen = mmc -> buflen;
|
||||
cgc.data_direction = CGC_DATA_READ;
|
||||
cgc.timeout = MMC_CMD_TIMEOUT * 1000; /* Linux uses milliseconds */
|
||||
cgc.sense = &sense;
|
||||
if (ioctl (dvd -> fd, CDROM_SEND_PACKET, &cgc) < 0 && !ignore_errors) {
|
||||
out = -1; /* Failure */
|
||||
error ("Execution of MMC command failed: %s", strerror (errno));
|
||||
debug ("Command was:");
|
||||
hex_and_ascii_print ("", cgc.cmd, sizeof (cgc.cmd));
|
||||
debug ("Sense data: %02X/%02X/%02X", sense.sense_key, sense.asc, sense.ascq);
|
||||
} else {
|
||||
out = 0;
|
||||
}
|
||||
|
||||
if (mmc -> sense) {
|
||||
mmc -> sense -> sense_key = sense.sense_key;
|
||||
mmc -> sense -> asc = sense.asc;
|
||||
mmc -> sense -> ascq = sense.ascq;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Sends an INQUIRY command to the drive to retrieve drive identification strings.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
static int dvd_get_drive_info (dvd_drive *dvd) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t buf[36];
|
||||
char tmp[36 * 4];
|
||||
|
||||
dvd_init_command (&mmc, buf, sizeof (buf), NULL);
|
||||
mmc.cmd[0] = SPC_INQUIRY;
|
||||
mmc.cmd[4] = sizeof (buf);
|
||||
if ((out = dvd_execute_cmd (dvd, &mmc, false)) >= 0) {
|
||||
my_strndup (dvd -> vendor, buf + 8, 8);
|
||||
strtrimr (dvd -> vendor);
|
||||
my_strndup (dvd -> prod_id, buf + 16, 16);
|
||||
strtrimr (dvd -> prod_id);
|
||||
my_strndup (dvd -> prod_rev, buf + 32, 4);
|
||||
strtrimr (dvd -> prod_rev);
|
||||
snprintf (tmp, sizeof (tmp), "%s/%s/%s", dvd -> vendor, dvd -> prod_id, dvd -> prod_rev);
|
||||
my_strdup (dvd -> model_string, tmp);
|
||||
|
||||
debug ("DVD drive is \"%s\"", dvd -> model_string);
|
||||
} else {
|
||||
error ("Cannot identify DVD drive\n");
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assigns the proper memory dump functions to a dvd_drive object, according to vendor, model and other parameters. Actually this scheme probably needs to
|
||||
* to be improved, but it is enough for the moment.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
*/
|
||||
static void dvd_assign_functions (dvd_drive *dvd, u_int32_t command) {
|
||||
dvd -> def_method = 0;
|
||||
if (strcmp (dvd -> vendor, "HL-DT-ST") == 0 && (
|
||||
// strcmp (dvd -> prod_id, "DVDRAM GSA-T10N") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8082N") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8161B") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8162B") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8163B") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8164B") == 0
|
||||
)) {
|
||||
debug ("Hitachi MN103-based DVD drive detected, using Hitachi memory dump command");
|
||||
dvd -> memdump = &hitachi_dvd_dump_mem;
|
||||
dvd -> command = 2;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 9;
|
||||
|
||||
} else if (strcmp (dvd -> vendor, "LITE-ON") == 0 && (
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-18A1H") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-18A1P") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-20A1H") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-20A1P") == 0
|
||||
)) {
|
||||
debug ("Lite-On DVD drive detected, using Lite-On memory dump command");
|
||||
dvd -> memdump = &liteon_dvd_dump_mem;
|
||||
dvd -> command = 3;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 5;
|
||||
|
||||
} else if (strcmp (dvd -> vendor, "TSSTcorp") == 0 && (
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162A") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162B") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162C") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162D") == 0
|
||||
)) {
|
||||
debug ("Toshiba Samsung DVD drive detected, using vanilla 2384 memory dump command");
|
||||
dvd -> memdump = &vanilla_2384_dvd_dump_mem;
|
||||
dvd -> command = 1;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 0;
|
||||
|
||||
} else if (strcmp (dvd -> vendor, "PLEXTOR") == 0) {
|
||||
debug ("Plextor DVD drive detected, using vanilla 2064 memory dump command");
|
||||
dvd -> memdump = &vanilla_2064_dvd_dump_mem;
|
||||
dvd -> command = 0;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 2;
|
||||
|
||||
} else {
|
||||
/* This is an unsupported drive (yet). */
|
||||
dvd -> memdump = &vanilla_2064_dvd_dump_mem;
|
||||
dvd -> command = 0;
|
||||
dvd -> supported = false;
|
||||
}
|
||||
|
||||
if (command!=-1) {
|
||||
dvd -> command = command;
|
||||
if (command == 0) dvd -> memdump = &vanilla_2064_dvd_dump_mem;
|
||||
else if (command == 1) dvd -> memdump = &vanilla_2384_dvd_dump_mem;
|
||||
else if (command == 2) dvd -> memdump = &hitachi_dvd_dump_mem;
|
||||
else if (command == 3) dvd -> memdump = &liteon_dvd_dump_mem;
|
||||
else if (command == 4) dvd -> memdump = &renesas_dvd_dump_mem;
|
||||
}
|
||||
|
||||
//init Reed-Solomon for Lite-On
|
||||
generate_gf();
|
||||
gen_poly();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new structure representing a CD/DVD-ROM drive.
|
||||
* @param device The CD/DVD-ROM device, in OS-dependent format (i.e.: /dev/something on Unix, x: on Windows).
|
||||
* @return The newly-created structure, to be used with the other commands, or NULL if the drive could not be initialized.
|
||||
*/
|
||||
dvd_drive *dvd_drive_new (char *device, u_int32_t command) {
|
||||
dvd_drive *dvd;
|
||||
#ifdef WIN32
|
||||
HANDLE fd;
|
||||
char dev[40];
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
/* Force the dropping of privileges: in our model, privileges are only used to execute memory dump commands, the user
|
||||
must gain access to the device somehow else (i. e. get added to the "cdrom" group or similar things) */
|
||||
drop_euid ();
|
||||
|
||||
debug ("Trying to open DVD device %s", device);
|
||||
#ifdef WIN32
|
||||
sprintf (dev, "\\\\.\\%c:", device[0]);
|
||||
if ((fd = CreateFile (dev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
|
||||
error ("Cannot open drive: %d", GetLastError ());
|
||||
#else
|
||||
if ((fd = open (device, O_RDONLY | O_NONBLOCK)) < 0) {
|
||||
perror ("Cannot open drive");
|
||||
#endif
|
||||
dvd = NULL;
|
||||
} else {
|
||||
debug ("Opened successfully");
|
||||
drop_euid ();
|
||||
dvd = (dvd_drive *) malloc (sizeof (dvd_drive));
|
||||
my_strdup (dvd -> device, device);
|
||||
dvd -> fd = fd;
|
||||
dvd_get_drive_info (dvd);
|
||||
dvd_assign_functions (dvd, command);
|
||||
}
|
||||
|
||||
return (dvd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees resources used by a DVD drive structure and destroys it.
|
||||
* @param dvd The DVD drive structure to be destroyed.
|
||||
* @return NULL.
|
||||
*/
|
||||
void *dvd_drive_destroy (dvd_drive *dvd) {
|
||||
if (dvd) {
|
||||
#ifdef WIN32
|
||||
CloseHandle (dvd -> fd);
|
||||
#else
|
||||
close (dvd -> fd);
|
||||
#endif
|
||||
my_free (dvd -> device);
|
||||
my_free (dvd -> vendor);
|
||||
my_free (dvd -> prod_id);
|
||||
my_free (dvd -> prod_rev);
|
||||
my_free (dvd);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the drive-dependent function to dump the drive sector cache, and returns the dumped data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param block_off The offset to start dumping, WRT the beginning of the sector cache.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size to be used for dumping.
|
||||
* @param buf A buffer where to store the dumped data. Note that this must be able to hold at least block_len * block_size bytes.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
int dvd_memdump (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
int out;
|
||||
|
||||
/* Upgrade privileges and call actual dump functions */
|
||||
upgrade_euid ();
|
||||
out = dvd -> memdump (dvd, block_off, block_len, block_size, buf);
|
||||
drop_euid ();
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues a READ(12) command without bothering to return the results. Uses the FUA (Force Unit Access bit) so that the requested sectors are actually read
|
||||
* at the beginning of the cache and can be dumped later.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param sector The sector to be read. What will be cached is the 16-sectors block to which the sector belongs.
|
||||
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
int dvd_read_sector_dummy (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64 * 1024], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
/* We need some buffer, be it provided externally or not */
|
||||
if (extbuf) {
|
||||
buf = extbuf;
|
||||
bufsize = extbufsize;
|
||||
} else {
|
||||
buf = intbuf;
|
||||
bufsize = sizeof (intbuf);
|
||||
}
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[1] = 0x08; /* FUA bit set */
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
mmc.cmd[6] = (u_int8_t) ((sectors & 0xFF000000) >> 24); /* Size from MSB to LSB */
|
||||
mmc.cmd[7] = (u_int8_t) ((sectors & 0x00FF0000) >> 16);
|
||||
mmc.cmd[8] = (u_int8_t) ((sectors & 0x0000FF00) >> 8);
|
||||
mmc.cmd[9] = (u_int8_t) (sectors & 0x000000FF);
|
||||
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues a READ(12) command using the STREAMING bit, which causes the requested 16-sector block to be read into memory,
|
||||
* together with the following four. This way we will be able to dump 5 sector with a single READ request.
|
||||
*
|
||||
* Note the strange need for a big buffer even though we must only pass 0x10 as the transfer length, otherwise the drive will hang (!?).
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param sector The sector to be read. What will be cached is the 16-sectors block to which the sector belongs, and the following 4 blocks.
|
||||
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed.
|
||||
* @param extbuf A buffer where to store the read data, or NULL.
|
||||
* @param extbufsize The size of the buffer.
|
||||
* @return
|
||||
*/
|
||||
int dvd_read_sector_streaming (dvd_drive *dvd, u_int32_t sector, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[2048 * 16], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
/* We need some buffer, be it provided externally or not */
|
||||
if (extbuf) {
|
||||
buf = extbuf;
|
||||
bufsize = extbufsize;
|
||||
} else {
|
||||
buf = intbuf;
|
||||
bufsize = sizeof (intbuf);
|
||||
}
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
mmc.cmd[6] = 0;
|
||||
mmc.cmd[7] = 0;
|
||||
mmc.cmd[8] = 0;
|
||||
mmc.cmd[9] = 0x10;
|
||||
mmc.cmd[10] = 0x80; /* STREAMING bit set */
|
||||
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
int dvd_read_streaming (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64 * 1024], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
/* We need some buffer, be it provided externally or not */
|
||||
if (extbuf) {
|
||||
buf = extbuf;
|
||||
bufsize = extbufsize;
|
||||
} else {
|
||||
buf = intbuf;
|
||||
bufsize = sizeof (intbuf);
|
||||
}
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
mmc.cmd[6] = (u_int8_t) ((sectors & 0xFF000000) >> 24); /* Size from MSB to LSB */
|
||||
mmc.cmd[7] = (u_int8_t) ((sectors & 0x00FF0000) >> 16);
|
||||
mmc.cmd[8] = (u_int8_t) ((sectors & 0x0000FF00) >> 8);
|
||||
mmc.cmd[9] = (u_int8_t) (sectors & 0x000000FF);
|
||||
mmc.cmd[10] = 0x80; /* STREAMING bit set */
|
||||
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
int dvd_flush_cache_READ12 (dvd_drive *dvd, u_int32_t sector, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[1] = 0x08;
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_stop_unit (dvd_drive *dvd, bool start, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0x1B;
|
||||
if (start) mmc.cmd[4] = 1;
|
||||
else mmc.cmd[4] = 0;
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_set_speed (dvd_drive *dvd, u_int32_t speed, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0xBB;
|
||||
mmc.cmd[2] = (u_int8_t) ((speed & 0x0000FF00) >> 8);
|
||||
mmc.cmd[3] = (u_int8_t) (speed & 0x000000FF);
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_get_size (dvd_drive *dvd, u_int32_t *size, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0x22;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0x52;
|
||||
mmc.cmd[1] = 0x01;
|
||||
mmc.cmd[5] = 0x01;
|
||||
mmc.cmd[8] = 0x22;
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
*(size)=*(size) << 8 | intbuf[0x18];
|
||||
*(size)=*(size) << 8 | intbuf[0x19];
|
||||
*(size)=*(size) << 8 | intbuf[0x1a];
|
||||
*(size)=*(size) << 8 | intbuf[0x1b];
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_get_layerbreak (dvd_drive *dvd, u_int32_t *layerbreak, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[2052], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 2052;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0xad;
|
||||
mmc.cmd[8] = 0x08;
|
||||
mmc.cmd[9] = 0x04;
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
*(layerbreak)=*(layerbreak) << 8;
|
||||
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x11];
|
||||
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x12];
|
||||
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x13];
|
||||
if (*(layerbreak) > 0) *(layerbreak)=*(layerbreak) - 0x30000 + 1;
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_set_streaming (dvd_drive *dvd, u_int32_t speed, req_sense *sense) {
|
||||
/*
|
||||
DVD Decrypter->
|
||||
DeviceIoControl : \Device\CdRom5
|
||||
Command : IOCTL_SCSI_PASS_THROUGH_DIRECT
|
||||
Length : 44 (0x002C)
|
||||
ScsiStatus : 0
|
||||
PathId : 0
|
||||
TargedId : 0
|
||||
Lun : 0
|
||||
CdbLength : 12 (0x0C)
|
||||
SenseInfoLength : 24 (0x18)
|
||||
DataTransferLength : 28 (0x0000001C)
|
||||
DataIn : 0
|
||||
TimeOutValue : 5000
|
||||
|
||||
CDB:
|
||||
00000000 B6 00 00 00 00 00 00 00 00 00 1C 00 ¶...........
|
||||
|
||||
Data Sent:
|
||||
00000000 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF ............____
|
||||
00000010 00 00 03 E8 FF FF FF FF 00 00 03 E8 ...è____...è
|
||||
*/
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t inbuf[28], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = inbuf;
|
||||
bufsize = 28;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[00] = 0xB6;
|
||||
mmc.cmd[10] = 28;
|
||||
|
||||
*(buf+ 0)=0;//2
|
||||
*(buf+ 1)=0;
|
||||
*(buf+ 2)=0;
|
||||
*(buf+ 3)=0;
|
||||
*(buf+ 4)=0; //MSB
|
||||
*(buf+ 5)=0; //
|
||||
*(buf+ 6)=0; //
|
||||
*(buf+ 7)=0; //LSB
|
||||
|
||||
*(buf+ 8)=0xff; //MSB
|
||||
*(buf+ 9)=0xff; //
|
||||
*(buf+10)=0xff; //
|
||||
*(buf+11)=0xff; //LSB
|
||||
|
||||
*(buf+12)=(u_int8_t) ((speed & 0xFF000000) >> 24);
|
||||
*(buf+13)=(u_int8_t) ((speed & 0x00FF0000) >> 16);
|
||||
*(buf+14)=(u_int8_t) ((speed & 0x0000FF00) >> 8);
|
||||
*(buf+15)=(u_int8_t) (speed & 0x000000FF);
|
||||
|
||||
*(buf+16)=(u_int8_t) ((1000 & 0xFF000000) >> 24);
|
||||
*(buf+17)=(u_int8_t) ((1000 & 0x00FF0000) >> 16);
|
||||
*(buf+18)=(u_int8_t) ((1000 & 0x0000FF00) >> 8);
|
||||
*(buf+19)=(u_int8_t) (1000 & 0x000000FF);
|
||||
|
||||
*(buf+20)=(u_int8_t) ((speed & 0xFF000000) >> 24);
|
||||
*(buf+21)=(u_int8_t) ((speed & 0x00FF0000) >> 16);
|
||||
*(buf+22)=(u_int8_t) ((speed & 0x0000FF00) >> 8);
|
||||
*(buf+23)=(u_int8_t) (speed & 0x000000FF);
|
||||
|
||||
*(buf+24)=(u_int8_t) ((1000 & 0xFF000000) >> 24);
|
||||
*(buf+25)=(u_int8_t) ((1000 & 0x00FF0000) >> 16);
|
||||
*(buf+26)=(u_int8_t) ((1000 & 0x0000FF00) >> 8);
|
||||
*(buf+27)=(u_int8_t) (1000 & 0x000000FF);
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_vendor (dvd_drive *dvd) {
|
||||
return (dvd -> vendor);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_product_id (dvd_drive *dvd) {
|
||||
return (dvd -> prod_id);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_product_revision (dvd_drive *dvd) {
|
||||
return (dvd -> prod_rev);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_model_string (dvd_drive *dvd) {
|
||||
return (dvd -> model_string);
|
||||
}
|
||||
|
||||
|
||||
bool dvd_get_support_status (dvd_drive *dvd) {
|
||||
return (dvd -> supported);
|
||||
}
|
||||
|
||||
u_int32_t dvd_get_def_method (dvd_drive *dvd){
|
||||
return (dvd -> def_method);
|
||||
}
|
||||
|
||||
u_int32_t dvd_get_command (dvd_drive *dvd){
|
||||
return (dvd -> command);
|
||||
}
|
73
libfriidump/dvd_drive.h
Normal file
73
libfriidump/dvd_drive.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DVD_DRIVE_H_INCLUDED
|
||||
#define DVD_DRIVE_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
typedef struct dvd_drive_s dvd_drive;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int sense_key;
|
||||
int asc;
|
||||
int ascq;
|
||||
} req_sense;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_int8_t cmd[12];
|
||||
req_sense *sense;
|
||||
u_int8_t *buffer;
|
||||
int buflen;
|
||||
} mmc_command;
|
||||
|
||||
|
||||
/* Functions */
|
||||
dvd_drive *dvd_drive_new (char *device, u_int32_t command);
|
||||
void *dvd_drive_destroy (dvd_drive *d);
|
||||
int dvd_read_sector_dummy (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
|
||||
int dvd_read_sector_streaming (dvd_drive *dvd, u_int32_t sector, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
|
||||
int dvd_read_streaming (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
|
||||
int dvd_flush_cache_READ12 (dvd_drive *dvd, u_int32_t sector, req_sense *sense);
|
||||
int dvd_stop_unit (dvd_drive *dvd, bool start, req_sense *sense);
|
||||
int dvd_set_speed (dvd_drive *dvd, u_int32_t speed, req_sense *sense);
|
||||
int dvd_get_size (dvd_drive *dvd, u_int32_t *size, req_sense *sense);
|
||||
int dvd_get_layerbreak (dvd_drive *dvd, u_int32_t *layerbreak, req_sense *sense);
|
||||
int dvd_set_streaming (dvd_drive *dvd, u_int32_t speed, req_sense *sense);
|
||||
int dvd_memdump (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
char *dvd_get_vendor (dvd_drive *dvd);
|
||||
char *dvd_get_product_id (dvd_drive *dvd);
|
||||
char *dvd_get_product_revision (dvd_drive *dvd);
|
||||
char *dvd_get_model_string (dvd_drive *dvd);
|
||||
bool dvd_get_support_status (dvd_drive *dvd);
|
||||
u_int32_t dvd_get_def_method (dvd_drive *dvd);
|
||||
u_int32_t dvd_get_command (dvd_drive *dvd);
|
||||
|
||||
/* The following are exported for use by drive-specific functions */
|
||||
typedef int (*dvd_drive_memdump_func) (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
void dvd_init_command (mmc_command *mmc, u_int8_t *buf, int len, req_sense *sense);
|
||||
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors);
|
||||
|
||||
#endif
|
109
libfriidump/ecma-267.c
Normal file
109
libfriidump/ecma-267.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
unscrambler 0.4: unscramble not standard IVs scrambled DVDs thru
|
||||
bruteforce, intended for Gamecube/WII Optical Disks.
|
||||
|
||||
Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ecma-267.h"
|
||||
|
||||
/* EDC stuff */
|
||||
unsigned int edc_table[256] = {
|
||||
0x00000000, 0x80000011, 0x80000033, 0x00000022, 0x80000077, 0x00000066, 0x00000044, 0x80000055,
|
||||
0x800000FF, 0x000000EE, 0x000000CC, 0x800000DD, 0x00000088, 0x80000099, 0x800000BB, 0x000000AA,
|
||||
0x800001EF, 0x000001FE, 0x000001DC, 0x800001CD, 0x00000198, 0x80000189, 0x800001AB, 0x000001BA,
|
||||
0x00000110, 0x80000101, 0x80000123, 0x00000132, 0x80000167, 0x00000176, 0x00000154, 0x80000145,
|
||||
0x800003CF, 0x000003DE, 0x000003FC, 0x800003ED, 0x000003B8, 0x800003A9, 0x8000038B, 0x0000039A,
|
||||
0x00000330, 0x80000321, 0x80000303, 0x00000312, 0x80000347, 0x00000356, 0x00000374, 0x80000365,
|
||||
0x00000220, 0x80000231, 0x80000213, 0x00000202, 0x80000257, 0x00000246, 0x00000264, 0x80000275,
|
||||
0x800002DF, 0x000002CE, 0x000002EC, 0x800002FD, 0x000002A8, 0x800002B9, 0x8000029B, 0x0000028A,
|
||||
0x8000078F, 0x0000079E, 0x000007BC, 0x800007AD, 0x000007F8, 0x800007E9, 0x800007CB, 0x000007DA,
|
||||
0x00000770, 0x80000761, 0x80000743, 0x00000752, 0x80000707, 0x00000716, 0x00000734, 0x80000725,
|
||||
0x00000660, 0x80000671, 0x80000653, 0x00000642, 0x80000617, 0x00000606, 0x00000624, 0x80000635,
|
||||
0x8000069F, 0x0000068E, 0x000006AC, 0x800006BD, 0x000006E8, 0x800006F9, 0x800006DB, 0x000006CA,
|
||||
0x00000440, 0x80000451, 0x80000473, 0x00000462, 0x80000437, 0x00000426, 0x00000404, 0x80000415,
|
||||
0x800004BF, 0x000004AE, 0x0000048C, 0x8000049D, 0x000004C8, 0x800004D9, 0x800004FB, 0x000004EA,
|
||||
0x800005AF, 0x000005BE, 0x0000059C, 0x8000058D, 0x000005D8, 0x800005C9, 0x800005EB, 0x000005FA,
|
||||
0x00000550, 0x80000541, 0x80000563, 0x00000572, 0x80000527, 0x00000536, 0x00000514, 0x80000505,
|
||||
0x80000F0F, 0x00000F1E, 0x00000F3C, 0x80000F2D, 0x00000F78, 0x80000F69, 0x80000F4B, 0x00000F5A,
|
||||
0x00000FF0, 0x80000FE1, 0x80000FC3, 0x00000FD2, 0x80000F87, 0x00000F96, 0x00000FB4, 0x80000FA5,
|
||||
0x00000EE0, 0x80000EF1, 0x80000ED3, 0x00000EC2, 0x80000E97, 0x00000E86, 0x00000EA4, 0x80000EB5,
|
||||
0x80000E1F, 0x00000E0E, 0x00000E2C, 0x80000E3D, 0x00000E68, 0x80000E79, 0x80000E5B, 0x00000E4A,
|
||||
0x00000CC0, 0x80000CD1, 0x80000CF3, 0x00000CE2, 0x80000CB7, 0x00000CA6, 0x00000C84, 0x80000C95,
|
||||
0x80000C3F, 0x00000C2E, 0x00000C0C, 0x80000C1D, 0x00000C48, 0x80000C59, 0x80000C7B, 0x00000C6A,
|
||||
0x80000D2F, 0x00000D3E, 0x00000D1C, 0x80000D0D, 0x00000D58, 0x80000D49, 0x80000D6B, 0x00000D7A,
|
||||
0x00000DD0, 0x80000DC1, 0x80000DE3, 0x00000DF2, 0x80000DA7, 0x00000DB6, 0x00000D94, 0x80000D85,
|
||||
0x00000880, 0x80000891, 0x800008B3, 0x000008A2, 0x800008F7, 0x000008E6, 0x000008C4, 0x800008D5,
|
||||
0x8000087F, 0x0000086E, 0x0000084C, 0x8000085D, 0x00000808, 0x80000819, 0x8000083B, 0x0000082A,
|
||||
0x8000096F, 0x0000097E, 0x0000095C, 0x8000094D, 0x00000918, 0x80000909, 0x8000092B, 0x0000093A,
|
||||
0x00000990, 0x80000981, 0x800009A3, 0x000009B2, 0x800009E7, 0x000009F6, 0x000009D4, 0x800009C5,
|
||||
0x80000B4F, 0x00000B5E, 0x00000B7C, 0x80000B6D, 0x00000B38, 0x80000B29, 0x80000B0B, 0x00000B1A,
|
||||
0x00000BB0, 0x80000BA1, 0x80000B83, 0x00000B92, 0x80000BC7, 0x00000BD6, 0x00000BF4, 0x80000BE5,
|
||||
0x00000AA0, 0x80000AB1, 0x80000A93, 0x00000A82, 0x80000AD7, 0x00000AC6, 0x00000AE4, 0x80000AF5,
|
||||
0x80000A5F, 0x00000A4E, 0x00000A6C, 0x80000A7D, 0x00000A28, 0x80000A39, 0x80000A1B, 0x00000A0AL
|
||||
};
|
||||
|
||||
u32 edc_calc(u32 edc, u8 *ptr, u32 len) {
|
||||
while (len--) edc=edc_table[((edc>>24)^*ptr++)&0xFF]^(edc<<8);
|
||||
return edc;
|
||||
}
|
||||
|
||||
/* end of EDC stuff */
|
||||
|
||||
/* LFSR stuff */
|
||||
|
||||
u16 ecma267_ivs[]= {
|
||||
0x0001, 0x5500, 0x0002, 0x2A00,
|
||||
0x0004, 0x5400, 0x0008, 0x2800,
|
||||
0x0010, 0x5000, 0x0020, 0x2001,
|
||||
0x0040, 0x4002, 0x0080, 0x0005
|
||||
};
|
||||
|
||||
|
||||
unsigned short LFSR;
|
||||
|
||||
void LFSR_ecma_init(int iv) {
|
||||
LFSR=ecma267_ivs[iv];
|
||||
}
|
||||
|
||||
void LFSR_init(u16 seed) {
|
||||
LFSR=seed;
|
||||
}
|
||||
|
||||
int LFSR_tick() {
|
||||
int ret;
|
||||
int n;
|
||||
|
||||
ret=LFSR>>14;
|
||||
|
||||
n=ret^((LFSR>>10)&1);
|
||||
LFSR=((LFSR<<1)|n)&0x7FFF;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char LFSR_byte() {
|
||||
u8 ret;
|
||||
int i;
|
||||
|
||||
ret=0;
|
||||
for(i=0; i<8; i++) ret=(ret<<1)|LFSR_tick();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end of LFSR stuff */
|
47
libfriidump/ecma-267.h
Normal file
47
libfriidump/ecma-267.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
unscrambler 0.4: unscramble not standard IVs scrambled DVDs thru
|
||||
bruteforce, intended for Gamecube/WII Optical Disks.
|
||||
|
||||
Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef int s32;
|
||||
|
||||
typedef unsigned short u16;
|
||||
typedef short s16;
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef char s8;
|
||||
|
||||
/* EDC stuff */
|
||||
|
||||
u32 edc_calc(u32 edc, u8 *ptr, u32 len);
|
||||
|
||||
/* end of EDC stuff */
|
||||
|
||||
/* LFSR stuff */
|
||||
|
||||
void LFSR_ecma_init(int iv);
|
||||
|
||||
void LFSR_init(u16 seed);
|
||||
|
||||
int LFSR_tick();
|
||||
|
||||
u8 LFSR_byte();
|
||||
|
||||
/* end of LFSR stuff */
|
147
libfriidump/hitachi.c
Normal file
147
libfriidump/hitachi.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief Memory dump functions specific to drives based on the Hitachi MN103 chip.
|
||||
*
|
||||
* Drives which are supported by this set of functions are, for instance, the LG GDR-8161B, GDR-8162B, GDR-8163B and GDR-8164B. All testing has been performed
|
||||
* with the latter model, so I'm not really sure about the others, but they should work ;). Please report any issues and more compatible drives!
|
||||
*
|
||||
* This file contains code derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/ , which, in turn, derives from work by
|
||||
* a lot of other people. See his page for full details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/*! \brief Memory offset at which the drive cache memory is mapped.
|
||||
*
|
||||
* During READ, sector data is cached beginning at this address.
|
||||
*/
|
||||
|
||||
#define HITACHI_MEM_BASE 0x80000000
|
||||
|
||||
|
||||
/**
|
||||
* Dumps a single block (with arbitrary size) of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive and similar drives.
|
||||
* This function is derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int hitachi_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || block_size > 65535) {
|
||||
error ("invalid block_size (valid: 1 - 65535)");
|
||||
out = -2;
|
||||
} else {
|
||||
dvd_init_command (&mmc, buf, block_size, NULL);
|
||||
mmc.cmd[0] = 0xE7; // vendor specific command (discovered by DaveX)
|
||||
mmc.cmd[1] = 0x48; // H
|
||||
mmc.cmd[2] = 0x49; // I
|
||||
mmc.cmd[3] = 0x54; // T
|
||||
mmc.cmd[4] = 0x01; // read MCU memory sub-command
|
||||
mmc.cmd[6] = (unsigned char) ((offset & 0xFF000000) >> 24); // address MSB
|
||||
mmc.cmd[7] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address
|
||||
mmc.cmd[8] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[9] = (unsigned char) (offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[10] = (unsigned char) ((block_size & 0xFF00) >> 8); // length MSB
|
||||
mmc.cmd[11] = (unsigned char) (block_size & 0x00FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dumps a given portion of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive.
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int hitachi_dvd_dump_mem_generic (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = hitachi_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("hitachi_dvd_read_block() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dumps a given portion of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive, starting at the offset at which
|
||||
* sector data are cached.
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int hitachi_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = hitachi_dvd_dump_memblock (dvd, HITACHI_MEM_BASE + offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("hitachi_dvd_read_block() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
154
libfriidump/lite-on.c
Normal file
154
libfriidump/lite-on.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H; verified with LH-18A1P and LH-20A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
//u_int8_t tmp[64*1024];
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int liteon_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int32_t raw_block_size;
|
||||
u_int32_t raw_offset;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t dst_offset;
|
||||
u_int32_t row_nr;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
u_int8_t tmp[64*1024];
|
||||
//u_int8_t *tmp;
|
||||
|
||||
raw_block_size = (block_size / 2064) * 0x950;
|
||||
raw_offset = (offset / 2064) * 0x950;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || raw_block_size >= 65535) {
|
||||
error ("invalid raw_block_size (valid: 1 - 65534)");
|
||||
error ("raw_block_size = (block_size / 2064) * 2384");
|
||||
out = -2;
|
||||
} else {
|
||||
//tmp = malloc(64*1024);
|
||||
dvd_init_command (&mmc, tmp, raw_block_size, NULL); //64*1024
|
||||
mmc.cmd[0] = 0x3C; // READ BUFFER
|
||||
mmc.cmd[1] = 0x01; // Vendor specific - sole parameter supported by Lite-On
|
||||
mmc.cmd[2] = 0x01; // == 0x02; 0xE2 = EEPROM; 0xF1 = KEYPARA;
|
||||
mmc.cmd[3] = (unsigned char) ((raw_offset & 0x00FF0000) >> 16);// address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((raw_offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( raw_offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[6] = (unsigned char) ((raw_block_size & 0x00FF0000) >> 16); // length MSB
|
||||
mmc.cmd[7] = (unsigned char) ((raw_block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( raw_block_size & 0x000000FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
dst_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < raw_block_size) {
|
||||
sec_nr=(*(tmp+src_offset+1)<<16)+(*(tmp+src_offset+2)<<8)+(*(tmp+src_offset+3));
|
||||
//fprintf (stdout,"sec_nr: %x\n", sec_nr);
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
rs_decode(tmp+src_offset, 0, 0);
|
||||
}
|
||||
else
|
||||
if (sec_nr==first_sec_nr+sec_cnt) {
|
||||
rs_decode(tmp+src_offset, 0, 0); //sector seq = ok
|
||||
}
|
||||
else { //sector seq broken -> corrupt
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(tmp+src_offset+0)=0xff;
|
||||
*(tmp+src_offset+1)=0xff;
|
||||
*(tmp+src_offset+2)=0xff;
|
||||
*(tmp+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
for (row_nr=0; row_nr<12; row_nr++) {
|
||||
memcpy(buf+dst_offset, tmp+src_offset, 172);
|
||||
dst_offset += 172;
|
||||
src_offset += 182;
|
||||
}
|
||||
src_offset += 200;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
//free(tmp);
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int liteon_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = liteon_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("liteon_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
314
libfriidump/misc.c
Normal file
314
libfriidump/misc.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
//#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
/*** LOGGING STUFF ***/
|
||||
/* Uses code from the printf man page */
|
||||
static int my_vasprintf (char **dst, const char *fmt, va_list ap) {
|
||||
char *p;
|
||||
int n, size;
|
||||
bool done;
|
||||
va_list ap2;
|
||||
|
||||
/* Guess we need no more than 100 bytes. */
|
||||
size = 100;
|
||||
if ((p = (char *) malloc (size)) != NULL) {
|
||||
do {
|
||||
done = false;
|
||||
va_copy (ap2, ap);
|
||||
n = vsnprintf (p, size, fmt, ap2);
|
||||
va_end (ap2);
|
||||
|
||||
/* If that worked, return the string. */
|
||||
if (n > -1 && n < size)
|
||||
done = true;
|
||||
else {
|
||||
/* Else try again with more space. */
|
||||
if (n > -1) /* glibc 2.1 */
|
||||
size = n + 1; /* precisely what is needed */
|
||||
else /* glibc 2.0 */
|
||||
size *= 2; /* twice the old size */
|
||||
|
||||
if ((p = (char *) realloc (p, size)) == NULL)
|
||||
done = true;
|
||||
}
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
/* Return -1 if memory allocation failed */
|
||||
if (!(*dst = p))
|
||||
n = -1;
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
|
||||
/* Appends a print-like string to the log file, with respect to the verbosity setting */
|
||||
void _logprintf (int level, char tag[], char format[], ...) {
|
||||
static bool last_nocr = false;
|
||||
char *buffer, t[50];
|
||||
va_list ap;
|
||||
struct timeval now;
|
||||
time_t nowtt;
|
||||
struct tm nowtm;
|
||||
|
||||
va_start (ap, format);
|
||||
my_vasprintf (&buffer, format, ap);
|
||||
va_end (ap);
|
||||
|
||||
/* Start of line, including time and tag */
|
||||
if (!last_nocr) {
|
||||
gettimeofday (&now, NULL);
|
||||
nowtt = (time_t) now.tv_sec;
|
||||
if (localtime_r (&nowtt, &nowtm))
|
||||
strftime (t, 50, "%H:%M:%S", &nowtm);
|
||||
if (tag)
|
||||
fprintf (stderr, "[%s/%s] ", t, tag);
|
||||
else
|
||||
fprintf (stderr, "[%s] ", t);
|
||||
|
||||
/* Debug level tag */
|
||||
if (level & LOG_WARNING)
|
||||
fprintf (stderr, "WARNING: ");
|
||||
else if (level & LOG_ERROR)
|
||||
fprintf (stderr, "ERROR: ");
|
||||
#ifdef DEBUG
|
||||
else if (level & LOG_DEBUG)
|
||||
fprintf (stderr, "DEBUG: ");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Actual message */
|
||||
fprintf (stderr, "%s%s", buffer, level & LOG_NOCR ? "" : "\n");
|
||||
fflush (stderr);
|
||||
free (buffer);
|
||||
|
||||
if (level & LOG_NOCR)
|
||||
last_nocr = true;
|
||||
else
|
||||
last_nocr = false;
|
||||
|
||||
return;
|
||||
}
|
||||
/******/
|
||||
|
||||
|
||||
/***************** TAKEN FROM TCPDUMP ****************/
|
||||
|
||||
#define ASCII_LINELENGTH 300
|
||||
#define HEXDUMP_BYTES_PER_LINE 16
|
||||
#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
|
||||
#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
|
||||
#define HEXDUMP_HEXSTUFF_PER_LINE (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
|
||||
|
||||
void hex_and_ascii_print_with_offset (const char *ident, register const u_int8_t *cp,
|
||||
register u_int16_t length, register u_int16_t oset) {
|
||||
register u_int16_t i;
|
||||
register int s1, s2;
|
||||
register int nshorts;
|
||||
char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
|
||||
char asciistuff[ASCII_LINELENGTH+1], *asp;
|
||||
|
||||
nshorts = length / sizeof(unsigned short);
|
||||
i = 0;
|
||||
hsp = hexstuff;
|
||||
asp = asciistuff;
|
||||
while (--nshorts >= 0) {
|
||||
s1 = *cp++;
|
||||
s2 = *cp++;
|
||||
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
|
||||
" %02x%02x", s1, s2);
|
||||
hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
|
||||
*(asp++) = (isgraph(s1) ? s1 : '.');
|
||||
*(asp++) = (isgraph(s2) ? s2 : '.');
|
||||
i++;
|
||||
if (i >= HEXDUMP_SHORTS_PER_LINE) {
|
||||
*hsp = *asp = '\0';
|
||||
(void)printf("%s0x%04x: %-*s %s",
|
||||
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
|
||||
hexstuff, asciistuff);
|
||||
i = 0;
|
||||
hsp = hexstuff;
|
||||
asp = asciistuff;
|
||||
oset += HEXDUMP_BYTES_PER_LINE;
|
||||
}
|
||||
}
|
||||
if (length & 1) {
|
||||
s1 = *cp++;
|
||||
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
|
||||
" %02x", s1);
|
||||
hsp += 3;
|
||||
*(asp++) = (isgraph(s1) ? s1 : '.');
|
||||
++i;
|
||||
}
|
||||
if (i > 0) {
|
||||
*hsp = *asp = '\0';
|
||||
debug ("%s0x%04x: %-*s %s",
|
||||
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
|
||||
hexstuff, asciistuff);
|
||||
}
|
||||
|
||||
debug ("\n"); // Final spacing
|
||||
}
|
||||
|
||||
char *strtrimr (char *s) {
|
||||
int i;
|
||||
|
||||
for (i = strlen (s) - 1; i >= 0 && isspace (s[i]); i--)
|
||||
s[i] = '\0';
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
/*** The following was taken from the Python sources */
|
||||
#if !defined(HAVE_LARGEFILE_SUPPORT)
|
||||
#error "Large file support must be enabled for this program"
|
||||
#else
|
||||
|
||||
/* A portable fseek() function
|
||||
return 0 on success, non-zero on failure (with errno set) */
|
||||
int my_fseek (FILE *fp, my_off_t offset, int whence) {
|
||||
#if defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8
|
||||
return fseeko(fp, offset, whence);
|
||||
#elif defined(_MSC_VER)
|
||||
return _fseeki64(fp, (__int64) offset, whence);
|
||||
#elif defined(HAVE_FSEEK64)
|
||||
return fseek64(fp, offset, whence);
|
||||
#elif defined(__BEOS__)
|
||||
return _fseek(fp, offset, whence);
|
||||
#elif SIZEOF_FPOS_T >= 8
|
||||
/* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()
|
||||
and fgetpos() to implement fseek()*/
|
||||
fpos_t pos;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_END:
|
||||
#ifdef MS_WINDOWS
|
||||
fflush (fp);
|
||||
if (_lseeki64 (fileno(fp), 0, 2) == -1)
|
||||
return -1;
|
||||
#else
|
||||
if (fseek (fp, 0, SEEK_END) != 0)
|
||||
return -1;
|
||||
#endif
|
||||
// fall through
|
||||
case SEEK_CUR:
|
||||
if (fgetpos (fp, &pos) != 0)
|
||||
return -1;
|
||||
offset += pos;
|
||||
break;
|
||||
// case SEEK_SET: break;
|
||||
}
|
||||
return fsetpos(fp, &offset);
|
||||
#else
|
||||
#error "Large file support, but no way to fseek."
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* A portable ftell() function
|
||||
Return -1 on failure with errno set appropriately, current file
|
||||
position on success */
|
||||
my_off_t my_ftell (FILE* fp) {
|
||||
#if defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8
|
||||
return ftello (fp);
|
||||
#elif defined(_MSC_VER)
|
||||
return _ftelli64 (fp);
|
||||
#elif defined(HAVE_FTELL64)
|
||||
return ftell64 (fp);
|
||||
#elif SIZEOF_FPOS_T >= 8
|
||||
fpos_t pos;
|
||||
|
||||
if (fgetpos (fp, &pos) != 0)
|
||||
return -1;
|
||||
|
||||
return pos;
|
||||
#else
|
||||
#error "Large file support, but no way to ftell."
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*** STUFF FOR DROPPING PRIVILEGES ***/
|
||||
|
||||
/* WARNING: I'm not sure at all that the privileges-dropping system I have implemented is secure, so don't rely too much on it. */
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Drops privileges to those of the real user (i. e. set euid to ruid).
|
||||
*/
|
||||
void drop_euid () {
|
||||
#ifndef WIN32
|
||||
uid_t uid, euid;
|
||||
|
||||
uid = getuid ();
|
||||
euid = geteuid ();
|
||||
if (uid != 0 && uid != euid) {
|
||||
#if 1
|
||||
seteuid (uid);
|
||||
#else
|
||||
if (seteuid (uid) != 0)
|
||||
debug ("seteuid() to uid %d failed", uid);
|
||||
else
|
||||
debug ("Changed euid from %d to %d", euid, uid);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Upgrades priviles to those of root (i. e. set euid to 0).
|
||||
*/
|
||||
void upgrade_euid () {
|
||||
#ifndef WIN32
|
||||
if (getuid () != 0) {
|
||||
#if 1
|
||||
seteuid (0);
|
||||
#else
|
||||
if (seteuid (0) != 0)
|
||||
debug ("seteuid() to root failed");
|
||||
else
|
||||
debug ("Changed euid to root");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
140
libfriidump/misc.h
Normal file
140
libfriidump/misc.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MISC_H_INCLUDED
|
||||
#define MISC_H_INCLUDED
|
||||
|
||||
/*** Include site configuration ***/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
/******/
|
||||
|
||||
/*** Windows stuff ***/
|
||||
#include "win32compat.h"
|
||||
|
||||
#define _GNU_SOURCE // For strndup()
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/*** ASSERTIONS ***/
|
||||
#define MY_ASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
fprintf (stderr, "*** ASSERTION FAILED at " __FILE__ ":%d: " # cond "\n", __LINE__); \
|
||||
exit (9); \
|
||||
}
|
||||
|
||||
/*** LOGGING STUFF ***/
|
||||
enum {
|
||||
LOG_NORMAL = 1 << 0,
|
||||
LOG_WARNING = 1 << 1,
|
||||
LOG_ERROR = 1 << 2,
|
||||
#ifdef DEBUG
|
||||
LOG_DEBUG = 1 << 4,
|
||||
#endif
|
||||
LOG_NOCR = 1 << 15 /* Use in OR to avoid a trailing newline */
|
||||
};
|
||||
|
||||
/* Don't use this function explicitly. Use the macros below. */
|
||||
void _logprintf (int level, char tag[], char format[], ...);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define logprintf(level, ...) _logprintf (level, (char *) __FUNCTION__, __VA_ARGS__)
|
||||
|
||||
#define debug(...) logprintf(LOG_DEBUG, __VA_ARGS__)
|
||||
#define debug_nocr(...) logprintf(LOG_DEBUG | LOG_NOCR, __VA_ARGS__)
|
||||
#else
|
||||
#define logprintf(level, ...) _logprintf (level, NULL, __VA_ARGS__)
|
||||
|
||||
#define debug(...) do {;} while (0);
|
||||
#define debug_nocr(...) do {;} while (0);
|
||||
#endif
|
||||
|
||||
#if defined (DEBUG) || defined (VERBOSE)
|
||||
#define log(...) logprintf (LOG_NORMAL, __VA_ARGS__)
|
||||
#define warning(...) logprintf (LOG_WARNING, __VA_ARGS__)
|
||||
#define error(...) logprintf (LOG_ERROR, __VA_ARGS__)
|
||||
#else
|
||||
#define log(...)
|
||||
#define warning(...)
|
||||
#define error(...)
|
||||
#endif
|
||||
/******/
|
||||
|
||||
void hex_and_ascii_print_with_offset(const char *ident, register const u_int8_t *cp,
|
||||
register u_int16_t length, register u_int16_t oset);
|
||||
#define hex_and_ascii_print(ident, cp, length) hex_and_ascii_print_with_offset(ident, cp, length, 0)
|
||||
|
||||
|
||||
#define my_strdup(dest, src) \
|
||||
if (!(dest = strdup (src))) { \
|
||||
fprintf (stderr, "strdup() failed\n"); \
|
||||
exit (101); \
|
||||
}
|
||||
|
||||
#define my_strndup(dest, src, c) \
|
||||
if (!(dest = strndup ((const char *) src, c))) { \
|
||||
fprintf (stderr, "strndup() failed\n"); \
|
||||
exit (102); \
|
||||
}
|
||||
|
||||
char *strtrimr (char *s);
|
||||
|
||||
#define my_free(p) \
|
||||
if (p) { \
|
||||
free (p); \
|
||||
p = NULL; \
|
||||
}
|
||||
|
||||
|
||||
/*** STUFF FOR PORTABLE LARGE-FILES FSEEK ***/
|
||||
#if defined (HAVE_OFF_T) && SIZEOF_OFF_T >= 8
|
||||
typedef off_t my_off_t;
|
||||
#elif defined (HAVE_FPOS_T) && SIZEOF_FPOS_T >= 8
|
||||
typedef fpos_t my_off_t;
|
||||
#else
|
||||
typedef u_int64_t my_off_t;
|
||||
#endif
|
||||
|
||||
int my_fseek (FILE *fp, my_off_t offset, int whence);
|
||||
my_off_t my_ftell (FILE* fp);
|
||||
/*******/
|
||||
|
||||
|
||||
/*** STUFF FOR DROPPING PRIVILEGES ***/
|
||||
FRIIDUMPLIB_EXPORT void drop_euid ();
|
||||
FRIIDUMPLIB_EXPORT void upgrade_euid ();
|
||||
/******/
|
||||
|
||||
|
||||
/*** STUFF FOR BOOLEAN DATA TYPE ***/
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
/* If using a C99 compiler, use the builtin boolean type */
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
typedef enum {false,true} bool;
|
||||
#endif
|
||||
/******/
|
||||
|
||||
#endif
|
132
libfriidump/renesas.c
Normal file
132
libfriidump/renesas.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int renesas_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || block_size > 65535) {
|
||||
error ("invalid block_size (valid: 1 - 65535)");
|
||||
out = -2;
|
||||
} else {
|
||||
dvd_init_command (&mmc, buf, block_size, NULL);
|
||||
mmc.cmd[0] = 0x3C;
|
||||
mmc.cmd[1] = 0x05;
|
||||
mmc.cmd[2] = (unsigned char) ((offset & 0xFF000000) >> 24); // address MSB
|
||||
mmc.cmd[3] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( offset & 0x000000FF); // address LSB
|
||||
// mmc.cmd[6] = (unsigned char) ((block_size & 0x00FF0000) >> 16);// length MSB
|
||||
mmc.cmd[6] = 0;
|
||||
mmc.cmd[7] = (unsigned char) ((block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( block_size & 0x000000FF); // length LSB
|
||||
mmc.cmd[9] = 0x44;
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < block_size) {
|
||||
sec_nr=(*(buf+src_offset+1)<<16)+(*(buf+src_offset+2)<<8)+(*(buf+src_offset+3));
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
}
|
||||
else
|
||||
if (sec_nr!=first_sec_nr+sec_cnt) {
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(buf+src_offset+0)=0xff;
|
||||
*(buf+src_offset+1)=0xff;
|
||||
*(buf+src_offset+2)=0xff;
|
||||
*(buf+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
src_offset += 2064;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int renesas_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = renesas_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("renesas_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
316
libfriidump/rs.c
Normal file
316
libfriidump/rs.c
Normal file
|
@ -0,0 +1,316 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define mm 8 /* RS code over GF(2**mm) - change to suit */
|
||||
#define n 256 /* n = size of the field */
|
||||
#define nn 182 /* nn=2**mm -1 length of codeword */
|
||||
#define kk 172 /* kk = nn-2*tt */ /* Degree of g(x) = 2*tt */
|
||||
|
||||
//#define NN n-1
|
||||
//#define FCR 0
|
||||
//#define PRIM 1
|
||||
#define _NROOTS nn-kk
|
||||
//#define PAD NN-nn
|
||||
//#define A0 NN
|
||||
//#define IPRIM 1
|
||||
|
||||
const int NN = n-1;
|
||||
const int FCR = 0;
|
||||
const int PRIM = 1;
|
||||
const int NROOTS = nn-kk;
|
||||
const int PAD = (n-1)-nn;
|
||||
const int A0 = n-1;
|
||||
const int IPRIM = 1;
|
||||
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/**** Primitive polynomial ****/
|
||||
int pp [mm+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1}; /* 1+x^2+x^3+x^4+x^8 */
|
||||
|
||||
/* generator polynomial, tables for Galois field */
|
||||
int alpha_to[n], index_of[n], gg[nn-kk+1];
|
||||
|
||||
int b0 = 1;
|
||||
|
||||
/* data[] is the info vector, bb[] is the parity vector, recd[] is the
|
||||
noise corrupted received vector */
|
||||
int recd[nn], data[kk], bb[nn-kk];
|
||||
|
||||
int modnn(int x){
|
||||
while (x >= 0xff) {
|
||||
x -= 0xff;
|
||||
x = (x >> 0xff) + (x & 0xff);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
void generate_gf()
|
||||
{
|
||||
register int i, mask ;
|
||||
|
||||
mask = 1 ;
|
||||
alpha_to[mm] = 0 ;
|
||||
for (i=0; i<mm; i++)
|
||||
{ alpha_to[i] = mask ;
|
||||
index_of[alpha_to[i]] = i ;
|
||||
if (pp[i]!=0) /* If pp[i] == 1 then, term @^i occurs in poly-repr of @^mm */
|
||||
alpha_to[mm] ^= mask ; /* Bit-wise EXOR operation */
|
||||
mask <<= 1 ; /* single left-shift */
|
||||
}
|
||||
index_of[alpha_to[mm]] = mm ;
|
||||
/* Have obtained poly-repr of @^mm. Poly-repr of @^(i+1) is given by
|
||||
poly-repr of @^i shifted left one-bit and accounting for any @^mm
|
||||
term that may occur when poly-repr of @^i is shifted. */
|
||||
mask >>= 1 ;
|
||||
for (i=mm+1; i<255; i++)
|
||||
{ if (alpha_to[i-1] >= mask)
|
||||
alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1]^mask)<<1) ;
|
||||
else alpha_to[i] = alpha_to[i-1]<<1 ;
|
||||
index_of[alpha_to[i]] = i ;
|
||||
}
|
||||
index_of[0] = A0 ;//-1
|
||||
}
|
||||
|
||||
|
||||
void gen_poly()
|
||||
/* Obtain the generator polynomial of the tt-error correcting, length */
|
||||
{
|
||||
register int i, j, root;
|
||||
|
||||
gg[0] = 1;
|
||||
|
||||
for (i = 0,root=0*1; i < nn-kk; i++,root += 1) {
|
||||
gg[i+1] = 1;
|
||||
|
||||
for (j = i; j > 0; j--){
|
||||
if (gg[j] != 0)
|
||||
gg[j] = gg[j-1] ^ alpha_to[modnn(index_of[gg[j]] + root)];
|
||||
else
|
||||
gg[j] = gg[j-1];
|
||||
}
|
||||
|
||||
gg[0] = alpha_to[modnn(index_of[gg[0]] + root)];
|
||||
}
|
||||
for (i=0; i <= nn-kk; i++) {
|
||||
gg[i] = index_of[gg[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rs_encode(unsigned char *data, unsigned char *bb)
|
||||
{
|
||||
register int i,j ;
|
||||
int feedback;
|
||||
|
||||
for (i=0; i<NROOTS; i++) bb[i] = 0; //nullify result
|
||||
|
||||
for(i=0;i<NN-NROOTS-PAD;i++){
|
||||
feedback = index_of[data[i] ^ bb[0]];
|
||||
|
||||
if(feedback != A0){ /* feedback term is non-zero */
|
||||
for(j=1;j<NROOTS;j++) {
|
||||
bb[j] ^= alpha_to[modnn(feedback + gg[NROOTS-j])];
|
||||
}
|
||||
}
|
||||
/* Shift */
|
||||
memmove(&bb[0],&bb[1], NROOTS-1);
|
||||
//for (j=0; j<NROOTS-1; j++) bb[j] = bb[j+1];
|
||||
|
||||
if(feedback != A0)
|
||||
bb[NROOTS-1] = alpha_to[modnn(feedback + gg[0])];
|
||||
else
|
||||
bb[NROOTS-1] = 0;
|
||||
}
|
||||
}
|
||||
///*
|
||||
int rs_decode(unsigned char *data, int *eras_pos, int no_eras){
|
||||
int deg_lambda, el, deg_omega;
|
||||
int i, j, r,k;
|
||||
unsigned char u,q,tmp,num1,num2,den,discr_r;
|
||||
unsigned char lambda[_NROOTS+1], s[_NROOTS];
|
||||
unsigned char b[_NROOTS+1], t[_NROOTS+1], omega[_NROOTS+1];
|
||||
unsigned char root[_NROOTS], reg[_NROOTS+1], loc[_NROOTS];
|
||||
int syn_error, count;
|
||||
|
||||
|
||||
// form the syndromes; i.e., evaluate data(x) at roots of g(x)
|
||||
for(i=0;i<NROOTS;i++)
|
||||
s[i] = data[0];
|
||||
|
||||
for(j=1;j<NN-PAD;j++){
|
||||
for(i=0;i<NROOTS;i++){
|
||||
if(s[i] == 0){
|
||||
s[i] = data[j];
|
||||
} else {
|
||||
s[i] = data[j] ^ alpha_to[modnn(index_of[s[i]] + (FCR+i)*PRIM)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert syndromes to index form, checking for nonzero condition
|
||||
syn_error = 0;
|
||||
for(i=0;i<NROOTS;i++){
|
||||
syn_error |= s[i];
|
||||
s[i] = index_of[s[i]];
|
||||
}
|
||||
|
||||
if (!syn_error) {
|
||||
// if syndrome is zero, data[] is a codeword and there are no
|
||||
// errors to correct. So return data[] unmodified
|
||||
//
|
||||
count = 0;
|
||||
goto finish;
|
||||
}
|
||||
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
|
||||
lambda[0] = 1;
|
||||
|
||||
if (no_eras > 0) {
|
||||
/* Init lambda to be the erasure locator polynomial */
|
||||
lambda[1] = alpha_to[modnn(PRIM*(NN-1-eras_pos[0]))];
|
||||
for (i = 1; i < no_eras; i++) {
|
||||
u = modnn(PRIM*(NN-1-eras_pos[i]));
|
||||
for (j = i+1; j > 0; j--) {
|
||||
tmp = index_of[lambda[j - 1]];
|
||||
if(tmp != A0)
|
||||
lambda[j] ^= alpha_to[modnn(u + tmp)];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0;i<NROOTS+1;i++)
|
||||
b[i] = index_of[lambda[i]];
|
||||
|
||||
/*
|
||||
* Begin Berlekamp-Massey algorithm to determine error+erasure
|
||||
* locator polynomial
|
||||
*/
|
||||
r = no_eras;
|
||||
el = no_eras;
|
||||
|
||||
while (++r <= NROOTS) { /* r is the step number */
|
||||
/* Compute discrepancy at the r-th step in poly-form */
|
||||
discr_r = 0;
|
||||
for (i = 0; i < r; i++){
|
||||
if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
|
||||
discr_r ^= alpha_to[modnn(index_of[lambda[i]] + s[r-i-1])];
|
||||
}
|
||||
}
|
||||
discr_r = index_of[discr_r]; /* Index form */
|
||||
if (discr_r == A0) {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
} else {
|
||||
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
|
||||
t[0] = lambda[0];
|
||||
for (i = 0 ; i < NROOTS; i++) {
|
||||
if(b[i] != A0)
|
||||
t[i+1] = lambda[i+1] ^ alpha_to[modnn(discr_r + b[i])];
|
||||
else
|
||||
t[i+1] = lambda[i+1];
|
||||
}
|
||||
if (2 * el <= r + no_eras - 1) {
|
||||
el = r + no_eras - el;
|
||||
/*
|
||||
* 2 lines below: B(x) <-- inv(discr_r) *
|
||||
* lambda(x)
|
||||
*/
|
||||
for (i = 0; i <= NROOTS; i++)
|
||||
b[i] = (lambda[i] == 0) ? A0 : modnn(index_of[lambda[i]] - discr_r + NN);
|
||||
} else {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
}
|
||||
memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert lambda to index form and compute deg(lambda(x)) */
|
||||
deg_lambda = 0;
|
||||
for(i=0;i<NROOTS+1;i++){
|
||||
lambda[i] = index_of[lambda[i]];
|
||||
if(lambda[i] != A0)
|
||||
deg_lambda = i;
|
||||
}
|
||||
/* Find roots of the error+erasure locator polynomial by Chien search */
|
||||
memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0]));
|
||||
count = 0; /* Number of roots of lambda(x) */
|
||||
for (i = 1,k=IPRIM-1; i <= NN; i++,k = modnn(k+IPRIM)) {
|
||||
q = 1; /* lambda[0] is always 0 */
|
||||
for (j = deg_lambda; j > 0; j--){
|
||||
if (reg[j] != A0) {
|
||||
reg[j] = modnn(reg[j] + j);
|
||||
q ^= alpha_to[reg[j]];
|
||||
}
|
||||
}
|
||||
if (q != 0)
|
||||
continue; /* Not a root */
|
||||
/* store root (index-form) and error location number */
|
||||
root[count] = i;
|
||||
loc[count] = k;
|
||||
/* If we've already found max possible roots,
|
||||
* abort the search to save time
|
||||
*/
|
||||
if(++count == deg_lambda)
|
||||
break;
|
||||
}
|
||||
|
||||
if (deg_lambda != count) {
|
||||
/*
|
||||
* deg(lambda) unequal to number of roots => uncorrectable
|
||||
* error detected
|
||||
*/
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
/*
|
||||
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
|
||||
* x**NROOTS). in index form. Also find deg(omega).
|
||||
*/
|
||||
deg_omega = deg_lambda-1;
|
||||
for (i = 0; i <= deg_omega;i++){
|
||||
tmp = 0;
|
||||
for(j=i;j >= 0; j--){
|
||||
if ((s[i - j] != A0) && (lambda[j] != A0))
|
||||
tmp ^= alpha_to[modnn(s[i - j] + lambda[j])];
|
||||
}
|
||||
omega[i] = index_of[tmp];
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
|
||||
* inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
|
||||
*/
|
||||
for (j = count-1; j >=0; j--) {
|
||||
num1 = 0;
|
||||
for (i = deg_omega; i >= 0; i--) {
|
||||
if (omega[i] != A0)
|
||||
num1 ^= alpha_to[modnn(omega[i] + i * root[j])];
|
||||
}
|
||||
num2 = alpha_to[modnn(root[j] * (FCR - 1) + NN)];
|
||||
den = 0;
|
||||
|
||||
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
|
||||
for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
|
||||
if(lambda[i+1] != A0)
|
||||
den ^= alpha_to[modnn(lambda[i+1] + i * root[j])];
|
||||
}
|
||||
/* Apply error to data */
|
||||
if (num1 != 0 && loc[j] >= PAD) {
|
||||
data[loc[j]-PAD] ^= alpha_to[modnn(index_of[num1] + index_of[num2] + NN - index_of[den])];
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
if(eras_pos != NULL){
|
||||
for(i=0;i<count;i++)
|
||||
eras_pos[i] = loc[i];
|
||||
}
|
||||
return count;
|
||||
}
|
10
libfriidump/rs.h
Normal file
10
libfriidump/rs.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int modnn(int x);
|
||||
void generate_gf();
|
||||
void gen_poly();
|
||||
void rs_encode(unsigned char *data, unsigned char *bb);
|
||||
int rs_decode(unsigned char *data, int *eras_pos, int no_eras);
|
370
libfriidump/unscrambler.c
Normal file
370
libfriidump/unscrambler.c
Normal file
|
@ -0,0 +1,370 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief Unscrambler for Nintendo GameCube/Wii discs.
|
||||
*
|
||||
* As Nintendo GameCube/Wii discs use the standars DVD-ROM scrambling algorithm, but with different, unknown, seeds, the actual seeds have to be brute-forced.
|
||||
* The functions in this file take care of the brute-forcing and of the actual unscrambling of the read sectors.
|
||||
*
|
||||
* The code in this file has been derived from unscrambler 0.4, Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl), GPL v2+,
|
||||
* http://www.ingenieria-inversa.cl/?lp_lang_pref=en .
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "constants.h"
|
||||
#include "byteorder.h"
|
||||
#include "ecma-267.h"
|
||||
#include "unscrambler.h"
|
||||
|
||||
// #define unscramblerdebug(...) debug (__VA_ARGS__);
|
||||
#define unscramblerdebug(...)
|
||||
|
||||
/*! \brief Size of the seeds cache (Do not touch) */
|
||||
#define MAX_SEEDS 4
|
||||
|
||||
/*! \brief Number of bytes of a sector on which the EDC is calculated */
|
||||
#define EDC_LENGTH (RAW_SECTOR_SIZE - 4) /* The EDC value is contained in the bottom 4 bytes of a frame */
|
||||
|
||||
|
||||
/*! \brief A structure that represents a seed
|
||||
*/
|
||||
typedef struct t_seed {
|
||||
int seed; //!< The seed, in numeric format.
|
||||
unsigned char streamcipher[SECTOR_SIZE]; //!< The stream cipher generated from the seed through the LFSR.
|
||||
} t_seed;
|
||||
|
||||
|
||||
/*! \brief A structure that represents an unscrambler
|
||||
*/
|
||||
struct unscrambler_s {
|
||||
t_seed seeds[(MAX_SEEDS + 1) * 16]; //!< The seeds cache.
|
||||
bool bruteforce_seeds; //!< If true, whenever a seed for a sector is not cached, it will be found via a bruteforce attack, otherwise an error will be returned.
|
||||
};
|
||||
|
||||
void unscrambler_set_disctype (u_int8_t disc_type){
|
||||
disctype = disc_type;
|
||||
// fprintf (stdout,"%d",disctype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a seed to the cache, calculating its streamcipher.
|
||||
* @param seeds The seed cache.
|
||||
* @param seed The seed to add.
|
||||
* @return A structure representing the added seed, or NULL if it could not be added.
|
||||
*/
|
||||
static t_seed *add_seed (t_seed *seeds, unsigned short seed) {
|
||||
int i;
|
||||
t_seed *out;
|
||||
|
||||
unscramblerdebug ("Caching seed %04x\n", seed);
|
||||
|
||||
if (seeds -> seed == -2) {
|
||||
out = NULL;
|
||||
} else {
|
||||
seeds -> seed = seed;
|
||||
|
||||
LFSR_init (seed);
|
||||
for (i = 0; i < SECTOR_SIZE; i++)
|
||||
seeds -> streamcipher[i] = LFSR_byte ();
|
||||
|
||||
out = seeds;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests if the specified seed is the one used for the specified sector block: the check is done comparing the generated EDC with the one at the bottom of each
|
||||
* sector. Sectors are processed in blocks, as the same seed is used for 16 consecutive sectors.
|
||||
* @param buf The sector.
|
||||
* @param j The seed.
|
||||
* @return true if the seed is correct, false otherwise.
|
||||
*/
|
||||
static bool test_seed (u_int8_t *buf, int j) {
|
||||
int i;
|
||||
u_int8_t tmp[RAW_SECTOR_SIZE];
|
||||
u_int32_t edc_calculated, edc_correct;
|
||||
bool out;
|
||||
|
||||
memcpy (tmp, buf, RAW_SECTOR_SIZE);
|
||||
|
||||
LFSR_init (j);
|
||||
for (i = 12; i < EDC_LENGTH; i++)
|
||||
tmp[i] ^= LFSR_byte ();
|
||||
|
||||
edc_calculated = edc_calc (0x00000000, tmp, EDC_LENGTH);
|
||||
edc_correct = my_ntohl (*((u_int32_t *) (&tmp[EDC_LENGTH])));
|
||||
if (edc_calculated == edc_correct)
|
||||
out = true;
|
||||
else
|
||||
out = false;
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unscramble a complete block, using an already-cached seed.
|
||||
* @param seed The seed to use for the unscrambling.
|
||||
* @param _bin The 16-sector block to unscramble (RAW_BLOCK_SIZE).
|
||||
* @param _bout The unscrambled 16-sector block (BLOCK_SIZE).
|
||||
* @return True if the unscrambling was successful, false otherwise.
|
||||
*/
|
||||
static bool unscramble_frame (t_seed *seed, u_int8_t *_bin, u_int8_t *_bout) {
|
||||
int i, j;
|
||||
u_int8_t tmp[RAW_SECTOR_SIZE], *bin, *bout;
|
||||
u_int32_t *_4bin, *_4cipher, edc_calculated, edc_correct;
|
||||
bool out;
|
||||
|
||||
out = true;
|
||||
for(j = 0; j < 16; j++) {
|
||||
bin = &_bin[RAW_SECTOR_SIZE * j];
|
||||
bout = &_bout[SECTOR_SIZE * j];
|
||||
|
||||
memcpy (tmp, bin, RAW_SECTOR_SIZE);
|
||||
_4bin = (u_int32_t *) &tmp[12]; /* Scrambled data begin at byte 12 */
|
||||
_4cipher = (u_int32_t *) seed -> streamcipher;
|
||||
for (i = 0; i < 512; i++) /* Well, the scrambling algorithm is just a bitwise XOR... */
|
||||
_4bin[i] ^= _4cipher[i];
|
||||
|
||||
//memcpy (bout, tmp + 6, SECTOR_SIZE); // copy CPR_MAI bytes
|
||||
|
||||
if (disctype==3) { //Regular
|
||||
memcpy (bout, tmp + 12, SECTOR_SIZE); // DVD: copy 2048 bytes (starting from CPR_MAI)
|
||||
}
|
||||
else { //Nintendo
|
||||
memcpy (bout, tmp + 6, SECTOR_SIZE); // Nintendo: copy 2048 bytes (up to CPR_MAI)
|
||||
memcpy (&_bin[(RAW_SECTOR_SIZE * j)+2054], &tmp[2054], 6);
|
||||
}
|
||||
|
||||
edc_calculated = edc_calc (0x00000000, tmp, EDC_LENGTH);
|
||||
edc_correct = my_ntohl (*((u_int32_t *) (&tmp[EDC_LENGTH])));
|
||||
if (edc_calculated != edc_correct) {
|
||||
debug ("Bad EDC (%08x), must be %08x (sector = %d)", edc_calculated, edc_correct, j);
|
||||
out = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the seed cache.
|
||||
* @param u The unscrambler structure.
|
||||
*/
|
||||
static void unscrambler_init_seeds (unscrambler *u) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < MAX_SEEDS; j++)
|
||||
u -> seeds[i * MAX_SEEDS + j].seed = -1;
|
||||
|
||||
u -> seeds[i * MAX_SEEDS + j].seed = -2; // TODO Check what this does
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new structure representing an unscrambler.
|
||||
* @return The newly-created structure, to be used with the other commands.
|
||||
*/
|
||||
unscrambler *unscrambler_new (void) {
|
||||
unscrambler *u;
|
||||
|
||||
u = (unscrambler *) malloc (sizeof (unscrambler));
|
||||
unscrambler_init_seeds (u);
|
||||
u -> bruteforce_seeds = true;
|
||||
|
||||
return (u);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees resources used by an unscrambler structure and destroys it.
|
||||
* @param u The unscrambler structure.
|
||||
* @return NULL.
|
||||
*/
|
||||
void *unscrambler_destroy (unscrambler *u) {
|
||||
my_free (u);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
void unscrambler_set_bruteforce (unscrambler *u, bool b) {
|
||||
u -> bruteforce_seeds = b;
|
||||
debug ("Seed bruteforcing %s", b ? "enabled" : "disabled");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unscrambles a 16-sector block.
|
||||
* @param u The unscrambler structure.
|
||||
* @param sector_no The number of the first sector in the block.
|
||||
* @param inbuf The 16-sector block to unscramble. Each block must be RAW_SECTOR_SIZE bytes long, so that the total size is RAW_BLOCK_SIZE.
|
||||
* @param outbuf The unscrambled 16-sector block. Each block will be SECTOR_SIZE bytes long, so that the total size is BLOCK_SIZE.
|
||||
* @return True if the unscrambling was successful, false otherwise.
|
||||
*/
|
||||
bool unscrambler_unscramble_16sectors (unscrambler *u, u_int32_t sector_no, u_int8_t *inbuf, u_int8_t *outbuf) {
|
||||
t_seed *seeds;
|
||||
t_seed *current_seed;
|
||||
int j;
|
||||
bool out;
|
||||
|
||||
out = true;
|
||||
|
||||
seeds = &(u -> seeds[((sector_no / 16) & 0x0F) * MAX_SEEDS]);
|
||||
|
||||
/* Try to find the seed used for this sector */
|
||||
current_seed = NULL;
|
||||
while (!current_seed && (seeds -> seed) >= 0) {
|
||||
if (test_seed (inbuf, seeds -> seed))
|
||||
current_seed = seeds;
|
||||
else
|
||||
seeds++;
|
||||
}
|
||||
|
||||
if (!current_seed && u -> bruteforce_seeds) {
|
||||
/* The seed is not cached, yet. Try to find it with brute force... */
|
||||
unscramblerdebug ("Brute-forcing seed for sector %d...", sector_no);
|
||||
|
||||
for (j = 0; !current_seed && j < 0x7FFF; j++) {
|
||||
if (test_seed (inbuf, j)) {
|
||||
if (!(current_seed = add_seed (seeds, j))) {
|
||||
error ("No enough cache space for caching seed");
|
||||
out = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_seed)
|
||||
unscramblerdebug ("Seed found: %04x", --j);
|
||||
}
|
||||
|
||||
if (current_seed) {
|
||||
/* OK, somehow seed was found: unscramble frame, write it and go on */
|
||||
if (!unscramble_frame (current_seed, inbuf, outbuf)) {
|
||||
error ("Error unscrambling frame %u\n", sector_no);
|
||||
out = false;
|
||||
} else {
|
||||
out = true;
|
||||
}
|
||||
} else {
|
||||
/* Well, we only get here if there are read errors */
|
||||
error ("Cannot find seed for frame %u", sector_no);
|
||||
out = false;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unscrambles a complete file.
|
||||
* @param u The unscrambler structure.
|
||||
* @param infile The input file name.
|
||||
* @param outfile The output file name.
|
||||
* @param progress A function to be called repeatedly during the operation, useful to report progress data/statistics.
|
||||
* @param progress_data Data to be passed as-is to the progress function.
|
||||
* @return True if the unscrambling was successful, false otherwise.
|
||||
*/
|
||||
bool unscrambler_unscramble_file (unscrambler *u, char *infile, char *outfile, unscrambler_progress_func progress, void *progress_data, u_int32_t *current_sector) {
|
||||
FILE *in, *outfp;
|
||||
bool out;
|
||||
u_int8_t b_in[RAW_BLOCK_SIZE], b_out[BLOCK_SIZE];
|
||||
size_t r;
|
||||
my_off_t filesize;
|
||||
int s;
|
||||
u_int32_t total_sectors;
|
||||
|
||||
out = false;
|
||||
if(!(in = fopen (infile ? infile : "", "rb"))) {
|
||||
error ("Cannot open input file \"%s\"", infile);
|
||||
} else if (!(outfp = fopen (outfile ? outfile : "", "wb"))) {
|
||||
error ("Cannot open output file \"%s\"", outfile);
|
||||
fclose (in);
|
||||
} else {
|
||||
/* Find out how many sectors we need to process */
|
||||
my_fseek (in, 0, SEEK_END);
|
||||
filesize = my_ftell (in);
|
||||
total_sectors = (u_int32_t) (filesize / RAW_SECTOR_SIZE);
|
||||
rewind (in);
|
||||
|
||||
/* First call to progress function */
|
||||
if (progress)
|
||||
progress (true, 0, total_sectors, progress_data);
|
||||
|
||||
s = 0, out = true;
|
||||
while ((r = fread (b_in, 1, RAW_BLOCK_SIZE, in)) > 0 && out) {
|
||||
if (r < RAW_BLOCK_SIZE) {
|
||||
warning ("Short block read (%u bytes), padding with zeroes!", r);
|
||||
memset (b_in + r, 0, sizeof (b_in) - r);
|
||||
}
|
||||
|
||||
if (unscrambler_unscramble_16sectors (u, s, b_in, b_out)) {
|
||||
clearerr (outfp);
|
||||
|
||||
if (!b_out) {
|
||||
error ("NULL buffer");
|
||||
out = false;
|
||||
*(current_sector) = s;
|
||||
}
|
||||
else fwrite (b_out, SECTOR_SIZE, SECTORS_PER_BLOCK, outfp);
|
||||
if (ferror (outfp)) {
|
||||
error ("fwrite() to ISO output file failed");
|
||||
out = false;
|
||||
*(current_sector) = s;
|
||||
}
|
||||
} else {
|
||||
debug ("unscrambler_unscramble_16sectors() failed");
|
||||
out = false;
|
||||
*(current_sector) = s;
|
||||
}
|
||||
|
||||
s += 16;
|
||||
|
||||
if ((s % 320 == 0) || (s == total_sectors)) { //speedhack
|
||||
if (progress)
|
||||
progress (false, s, total_sectors, progress_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (out) {
|
||||
debug ("Image successfully unscrambled");
|
||||
}
|
||||
|
||||
fclose (in);
|
||||
fclose (outfp);
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
43
libfriidump/unscrambler.h
Normal file
43
libfriidump/unscrambler.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef UNSCRAMBLER_H_INCLUDED
|
||||
#define UNSCRAMBLER_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct unscrambler_s unscrambler;
|
||||
|
||||
/* We want this module to be independent of the library framework, so that it can be easily recycled. Hence we just define the type of
|
||||
the progress function the same format we use elsewhere */
|
||||
typedef void (*unscrambler_progress_func) (bool start, u_int32_t current_sector, u_int32_t total_sectors, void *progress_data);
|
||||
|
||||
u_int8_t disctype;
|
||||
|
||||
FRIIDUMPLIB_EXPORT unscrambler *unscrambler_new (void);
|
||||
FRIIDUMPLIB_EXPORT void *unscrambler_destroy (unscrambler *u);
|
||||
FRIIDUMPLIB_EXPORT bool unscrambler_unscramble_16sectors (unscrambler *u, u_int32_t sector_no, u_int8_t *inbuf, u_int8_t *outbuf);
|
||||
FRIIDUMPLIB_EXPORT bool unscrambler_unscramble_file (unscrambler *u, char *infile, char *outfile, unscrambler_progress_func progress, void *progress_data, u_int32_t *current_sector);
|
||||
FRIIDUMPLIB_EXPORT void unscrambler_set_bruteforce (unscrambler *u, bool b);
|
||||
FRIIDUMPLIB_EXPORT void unscrambler_set_disctype (u_int8_t disc_type);
|
||||
|
||||
#endif
|
131
libfriidump/vanilla_2064.c
Normal file
131
libfriidump/vanilla_2064.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
//#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2064_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || block_size > 65535) {
|
||||
error ("invalid block_size (valid: 1 - 65535)");
|
||||
out = -2;
|
||||
} else {
|
||||
dvd_init_command (&mmc, buf, block_size, NULL);
|
||||
mmc.cmd[0] = 0x3C;
|
||||
mmc.cmd[1] = 0x02;
|
||||
mmc.cmd[2] = 0x00;
|
||||
mmc.cmd[3] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[6] = (unsigned char) ((block_size & 0x00FF0000) >> 16);// length MSB
|
||||
mmc.cmd[7] = (unsigned char) ((block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( block_size & 0x000000FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < block_size) {
|
||||
sec_nr=(*(buf+src_offset+1)<<16)+(*(buf+src_offset+2)<<8)+(*(buf+src_offset+3));
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
}
|
||||
else
|
||||
if (sec_nr!=first_sec_nr+sec_cnt) {
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(buf+src_offset+0)=0xff;
|
||||
*(buf+src_offset+1)=0xff;
|
||||
*(buf+src_offset+2)=0xff;
|
||||
*(buf+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
src_offset += 2064;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2064_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = vanilla_2064_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("vanilla_2064_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
153
libfriidump/vanilla_2384.c
Normal file
153
libfriidump/vanilla_2384.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
//#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
//u_int8_t tmp[64*1024];
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2384_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int32_t raw_block_size;
|
||||
u_int32_t raw_offset;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t dst_offset;
|
||||
u_int32_t row_nr;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
u_int8_t tmp[64*1024];
|
||||
//u_int8_t *tmp;
|
||||
|
||||
raw_block_size = (block_size / 2064) * 0x950;
|
||||
raw_offset = (offset / 2064) * 0x950;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || raw_block_size > 65535) {
|
||||
error ("invalid raw_block_size (valid: 1 - 65535)");
|
||||
error ("raw_block_size = (block_size / 2064) * 2384");
|
||||
out = -2;
|
||||
} else {
|
||||
//tmp = malloc(64*1024);
|
||||
dvd_init_command (&mmc, tmp, raw_block_size, NULL);
|
||||
mmc.cmd[0] = 0x3C;
|
||||
mmc.cmd[1] = 0x02;
|
||||
mmc.cmd[2] = 0x00;
|
||||
mmc.cmd[3] = (unsigned char) ((raw_offset & 0x00FF0000) >> 16);// address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((raw_offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( raw_offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[6] = (unsigned char) ((raw_block_size & 0x00FF0000) >> 16); // length MSB
|
||||
mmc.cmd[7] = (unsigned char) ((raw_block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( raw_block_size & 0x000000FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
dst_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < raw_block_size) {
|
||||
sec_nr=(*(tmp+src_offset+1)<<16)+(*(tmp+src_offset+2)<<8)+(*(tmp+src_offset+3));
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
// rs_decode(tmp+src_offset, 0, 0);
|
||||
}
|
||||
else
|
||||
if (sec_nr==first_sec_nr+sec_cnt) {
|
||||
// rs_decode(tmp+src_offset, 0, 0); //sector seq = ok
|
||||
}
|
||||
else { //sector seq broken -> corrupt
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(tmp+src_offset+0)=0xff;
|
||||
*(tmp+src_offset+1)=0xff;
|
||||
*(tmp+src_offset+2)=0xff;
|
||||
*(tmp+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
for (row_nr=0; row_nr<12; row_nr++) {
|
||||
memcpy(buf+dst_offset, tmp+src_offset, 172);
|
||||
dst_offset += 172;
|
||||
src_offset += 182;
|
||||
}
|
||||
src_offset += 200;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
//free(tmp);
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2384_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = vanilla_2384_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("vanilla_2384_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
75
libfriidump/win32compat.c
Normal file
75
libfriidump/win32compat.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32compat.h"
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
|
||||
char *strndup (const char *src, int c) {
|
||||
char *dest;
|
||||
|
||||
if ((dest = (char *) malloc ((c + 1) * sizeof (char)))) {
|
||||
memcpy (dest, src, c);
|
||||
dest[c] = '\0';
|
||||
}
|
||||
|
||||
return (dest);
|
||||
}
|
||||
|
||||
|
||||
int ftruncate (int fd, __int64 size) {
|
||||
return (_chsize_s (fd, size));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The following gettimeofday() replacement function was taken from Snort, GPLv2 */
|
||||
/****************************************************************************
|
||||
*
|
||||
* Function: gettimeofday(struct timeval *, struct timezone *)
|
||||
*
|
||||
* Purpose: Get current time of day.
|
||||
*
|
||||
* Arguments: tv => Place to store the curent time of day.
|
||||
* tz => Ignored.
|
||||
*
|
||||
* Returns: 0 => Success.
|
||||
*
|
||||
****************************************************************************/
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
struct _timeb tb;
|
||||
|
||||
if (tv == NULL) {
|
||||
return -1;
|
||||
}
|
||||
_ftime(&tb);
|
||||
tv->tv_sec = (long) tb.time;
|
||||
tv->tv_usec = ((int) tb.millitm) * 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
68
libfriidump/win32compat.h
Normal file
68
libfriidump/win32compat.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* 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 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/*** WINDOWS COMPATIBILITY STUFF ***/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
|
||||
/* Stuff to export library symbols */
|
||||
#ifdef FRIIDUMPLIB_BUILD_DLL
|
||||
#ifdef FRIIDUMPLIB_EXPORTS
|
||||
#define FRIIDUMPLIB_EXPORT __declspec(dllexport) /* Building the lib */
|
||||
#else
|
||||
#define FRIIDUMPLIB_EXPORT __declspec(dllimport) /* Building user code */
|
||||
#endif
|
||||
#else
|
||||
#define FRIIDUMPLIB_EXPORT
|
||||
#endif
|
||||
|
||||
/* Definition of the types we use for Windows */
|
||||
#define u_int8_t BYTE
|
||||
#define u_int16_t WORD
|
||||
#define int32_t INT32
|
||||
#define u_int32_t DWORD
|
||||
#define int64_t INT64
|
||||
#define u_int64_t ULONGLONG
|
||||
typedef long suseconds_t;
|
||||
|
||||
/* Some functions have different names */
|
||||
#define snprintf _snprintf
|
||||
#define strdup _strdup
|
||||
#define strcasecmp lstrcmpi
|
||||
#define va_copy(ap1, ap2) ((ap1) = (ap2)) // MSVC doesn't have va_copy, how crap...
|
||||
|
||||
/* Some functions do not exist (export them for applications, too) */
|
||||
FRIIDUMPLIB_EXPORT char *strndup (const char *src, int c);
|
||||
FRIIDUMPLIB_EXPORT int ftruncate (int fd, __int64 size);
|
||||
FRIIDUMPLIB_EXPORT int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
|
||||
/* Windows does have a different localtime() */
|
||||
#define localtime_r(x, y) !localtime_s (y, x)
|
||||
|
||||
#else
|
||||
|
||||
#define FRIIDUMPLIB_EXPORT
|
||||
|
||||
#endif
|
||||
/******/
|
Loading…
Add table
Add a link
Reference in a new issue