From clauflibitFriiDump-0.5.3.1

This commit is contained in:
Braden McDaniel 2013-11-01 12:26:04 -04:00
parent fe937e7f4b
commit 87b108d6a1
63 changed files with 11067 additions and 26 deletions

105
libfriidump/CMakeLists.txt Normal file
View 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)

View 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 */

View 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
View 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
View 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

File diff suppressed because it is too large Load diff

94
libfriidump/disc.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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(&reg[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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
/******/