/*
* This file is part of libbdplus
* Copyright (C) 2008-2010 Accident
* Copyright (C) 2013 VideoLAN
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* .
*/
#include "loader.h"
#include "dlx.h"
#include "file/file.h"
#include "util/logging.h"
#include "util/macro.h"
#include "util/strutl.h"
#include
static int _code_version_check(uint8_t *hdr, int *p_gen, int *p_date)
{
// known BD+ content code generations
static const uint16_t gentbl[][3] = {
//
// Year,Month,Day Manufacturer First title Notes
//
{ 2007, 6, 8 }, // gen 1: CRI "The Day After Tomorrow" First BD+. Content watermarking.
{ 2007, 12, 20 }, // gen 2: "Mrs Doubtfire" TRAP_MediaCheck (checks if content is encrypted with AACS).
{ 2008, 4, 14 }, // gen 3: Macrovision "Jumper" Useless FUEs, TRAP_DebugLog, BD-J <-> BD+ handshake.
{ 2008, 8, 22 }, // gen 4: "Futurama: Benders Game" MK.enc (encrypted java code).
{ 2009, 2, 2 }, // gen 5: "Slumdog Millionaire" Variable handshake return codes.
{ 2009, 3, 31 }, // gen 6: "Valkyrie" MK.enc --> 77773.jar
{ 2009, 8, 18 }, // gen 7: "Ice Age 3" 00003.svm
{ 2010, 3, 6 }, // gen 8: "Avatar" Native code. Permanent handshake during playback.
{ 2010, 9, 3 }, // gen 9: "Knight and Day" 00004.svm, 00005.svm. New native code.
{ 2011, 2, 28 }, // gen 10: "Rabbit Hole"
{ 2011, 6, 1 }, // gen 11: "Star Wars"
{ 2011, 11, 16 }, // gen 12/13: Irdeto "Contagion"
{ 2011, 11, 16 }, // -,,-
{ 2012, 8, 7 }, // gen 14: "Prometheus"
{ 2013, 1, 25 }, // gen 15: "Parental Guidance"
{ 2013, 4, 30 }, // gen 16: "Stoker" StreetLock.
};
unsigned int year = hdr[0x0d] << 8 | hdr[0x0e];
unsigned int month = hdr[0x0f];
unsigned int day = hdr[0x10];
unsigned int gen;
for (gen = 0; gen < sizeof(gentbl) / sizeof(gentbl[0]); gen++) {
if ( year < gentbl[gen][0] ||
(year == gentbl[gen][0] && month < gentbl[gen][1]) ||
(year == gentbl[gen][0] && month == gentbl[gen][1] && day < gentbl[gen][2])) {
break;
}
}
BD_DEBUG(DBG_BDPLUS, "[bdplus] BD+ code created: %04d-%02d-%02d (BD+ generation %d)\n", year, month, day, gen);
if (p_gen) {
*p_gen = gen;
}
if (p_date) {
*p_date = (hdr[0x0d] << 24) | (hdr[0x0e] << 16) | (hdr[0x0f] << 8) | hdr[0x10];
}
if (gen > 3) {
BD_DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] WARNING: BD+ generation %d not tested / supported\n", gen);
return -1;
}
return 0;
}
int32_t loader_load_svm(BDPLUS_FILE_H *fp, const char *fname, VM *vm, int *p_gen, int *p_date)
{
uint32_t len;
uint8_t *addr = dlx_getAddr(vm);
// Read BD SVM header
if (file_read(fp, addr, 0x18) != 0x18) {
BD_DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error reading header from %s\n", fname);
return -1;
}
if (memcmp(addr, "BDSVM_CC", 8)) {
BD_DEBUG(DBG_BDPLUS | DBG_CRIT,"[bdplus] %s failed signature match\n", fname);
}
_code_version_check(addr, p_gen, p_date);
// Pull out length
len = FETCH4(&addr[0x14]);
BD_DEBUG(DBG_BDPLUS,"[bdplus] svm size %08X (%u)\n", len, len);
if (len >= dlx_getAddrSize(vm)) {
BD_DEBUG(DBG_BDPLUS | DBG_CRIT,"[bdplus] Section too long (%d) in %s\n", len, fname);
return -1;
}
// read length data
if (file_read(fp, addr, len) != len) {
BD_DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error reading section from %s\n", fname);
return -1;
}
file_close(fp);
BD_DEBUG(DBG_BDPLUS,"[bdplus] loaded core '%s'\n", fname);
// clear first 0x1000 bytes
memset(addr, 0, 0x1000);
return 0;
}