Commit bc9cadcc authored by anonymous's avatar anonymous
Browse files

Add bdplus_set_fopen()

parent e04f080b
......@@ -35,6 +35,9 @@ libbdplus_la_SOURCES=\
libbdplus/bdsvm/sha1.h \
libbdplus/bdsvm/sha1.c \
file/dirs.h \
file/file.h \
file/file_default.c \
file/file_default.h \
file/configfile.c \
file/configfile.h \
util/attributes.h \
......
/*
* This file is part of libbdplus
* Copyright (C) 2015 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef FILE_H_
#define FILE_H_
#include "filesystem.h"
#ifdef _WIN32
# define DIR_SEP "\\"
#else
# define DIR_SEP "/"
#endif
/*
* file access
*/
#define file_close(X) X->close(X)
#define file_seek(X,Y,Z) X->seek(X,Y,Z)
#define file_read(X,Y,Z) X->read(X,Y,Z)
#define file_open(cfg, fname) (cfg->fopen(cfg->fopen_handle, fname))
#endif /* FILE_H_ */
/*
* This file is part of libaacs
* Copyright (C) 2015 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
* <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(__MINGW32__)
/* fseeko64() prototypes from stdio.h */
# undef __STRICT_ANSI__
# define fseeko fseeko64
#endif
#include "file_default.h"
#include "file.h"
#include "util/macro.h"
#include "util/strutl.h"
#include <stdio.h>
#include <stdlib.h>
static void _file_close(BDPLUS_FILE_H *file)
{
if (file) {
fclose((FILE *)file->internal);
X_FREE(file);
}
}
static int64_t _file_seek(BDPLUS_FILE_H *file, int64_t offset, int32_t origin)
{
return fseeko((FILE *)file->internal, offset, origin);
}
static int64_t _file_read(BDPLUS_FILE_H *file, uint8_t *buf, int64_t size)
{
return fread(buf, 1, size, (FILE *)file->internal);
}
BDPLUS_FILE_H *file_open_default(void *handle, const char* file_name)
{
const char *device_root = handle;
char *file_path;
BDPLUS_FILE_H *file;
FILE *fp;
file_path = str_printf("%s"DIR_SEP"%s", device_root, file_name);
fp = fopen(file_path, "rb");
X_FREE(file_path);
if (!fp) {
return NULL;
}
file = calloc(1, sizeof(BDPLUS_FILE_H));
file->internal = fp;
file->close = _file_close;
file->seek = _file_seek;
file->read = _file_read;
return file;
}
/*
* This file is part of libbdplus
* Copyright (C) 2015 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef FILE_DEFAULT_H_
#define FILE_DEFAULT_H_
#include "filesystem.h"
#include <util/attributes.h>
BD_PRIVATE BDPLUS_FILE_H *file_open_default(void *root_path, const char *file_name);
#endif /* FILE_DEFAULT_H_ */
/*
* This file is part of libbdplus
* Copyright (C) 2015 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef BDPLUS_FILESYSTEM_H_
#define BDPLUS_FILESYSTEM_H_
#include <stdint.h>
/* Keep this compatible with libaacs ! */
typedef struct bdplus_file BDPLUS_FILE_H;
struct bdplus_file
{
void *internal;
void (*close) (BDPLUS_FILE_H *file);
int64_t (*seek) (BDPLUS_FILE_H *file, int64_t offset, int32_t origin);
int64_t (*tell) (BDPLUS_FILE_H *file);
int (*eof) (BDPLUS_FILE_H *file);
int64_t (*read) (BDPLUS_FILE_H *file, uint8_t *buf, int64_t size);
int64_t (*write) (BDPLUS_FILE_H *file, const uint8_t *buf, int64_t size);
};
/**
*
* Function that will be used to open a file
*
* NOTE: file name is relative to disc root directory !
*
* @param handle application-specific handle
* @param filename file to open
* @return pointer to BDPLUS_FILE_H, NULL if error
*/
typedef BDPLUS_FILE_H* (*BDPLUS_FILE_OPEN)(void *handle, const char *filename);
/**
*
* Register function pointer that will be used to open a file
*
* @param bdplus bdplus instance
* @param handle handle that will be passed to file open function
* @param p function pointer
*/
struct bdplus_s;
void bdplus_set_fopen(struct bdplus_s *bdplus, void *handle, BDPLUS_FILE_OPEN p);
#endif /* BDPLUS_FILESYSTEM_H_ */
......@@ -35,6 +35,7 @@
#include "util/mutex.h"
#include "util/strutl.h"
#include "file/configfile.h"
#include "file/file_default.h"
#include <string.h>
#include <stdlib.h>
......@@ -54,15 +55,36 @@ void bdplus_get_version(int *major, int *minor, int *micro)
*micro = BDPLUS_VERSION_MICRO;
}
static int _load_svm(bdplus_t *plus)
{
if (!plus->config->fopen) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "No device path or filesystem access function provided\n");
return -1;
}
DEBUG(DBG_BDPLUS, "[bdplus] loading BDSVM/00000.svm...\n");
if (bdplus_load_svm(plus, "BDSVM/00000.svm")) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error loading BDSVM/00000.svm\n");
return -1;
}
plus->loaded = 1;
return 0;
}
int32_t bdplus_get_code_gen(bdplus_t *plus)
{
if (!plus) return -1;
if (!plus->loaded && _load_svm(plus) < 0) return -1;
return plus->gen;
}
int32_t bdplus_get_code_date(bdplus_t *plus)
{
if (!plus) return -1;
if (!plus->loaded && _load_svm(plus) < 0) return -1;
return plus->date;
}
......@@ -95,16 +117,11 @@ bdplus_t *bdplus_init(const char *path, const char *config_path, const uint8_t *
// Change to TEAM BLUH-RAY, DOOM9 FORUMS.
DEBUG(DBG_BDPLUS, "[bdplus] initialising...\n");
if (!path) {
DEBUG(DBG_BDPLUS, "No path\n");
return NULL;
}
/* Ensure libgcrypt is initialized before doing anything else */
DEBUG(DBG_BDPLUS, "Initializing libgcrypt...\n");
if (!crypto_init())
{
DEBUG(DBG_BDPLUS, "Failed to initialize libgcrypt\n");
DEBUG(DBG_BDPLUS | DBG_CRIT, "Failed to initialize libgcrypt\n");
return NULL;
}
......@@ -118,7 +135,10 @@ bdplus_t *bdplus_init(const char *path, const char *config_path, const uint8_t *
memset(plus, 0, sizeof(*plus)); // I just don't like calloc, strange..
bdplus_config_load(config_path, &plus->config);
if (bdplus_config_load(config_path, &plus->config) < 0) {
X_FREE(plus);
return NULL;
}
plus->free_slot = BDPLUS_NUM_SLOTS-1;
......@@ -126,18 +146,25 @@ bdplus_t *bdplus_init(const char *path, const char *config_path, const uint8_t *
plus->attachedStatus[0] = 0;
plus->attachedStatus[1] = 7;
plus->device_path = (char*)malloc(strlen(path) + 1);
strcpy(plus->device_path, path);
if (path) {
plus->device_path = (char*)malloc(strlen(path) + 1);
strcpy(plus->device_path, path);
plus->config->fopen_handle = plus->device_path;
plus->config->fopen = file_open_default;
}
plus->mutex = calloc(1, sizeof(BD_MUTEX));
bd_mutex_init(plus->mutex);
DEBUG(DBG_BDPLUS, "[bdplus] loading BDSVM/00000.svm and flash.bin...\n");
if (bdplus_load_svm(plus, "BDSVM/00000.svm")) {
DEBUG(DBG_BDPLUS, "[bdplus] Error loading BDSVM/00000.svm\n");
bdplus_free(plus);
return NULL;
if (plus->config->fopen) {
if (_load_svm(plus) < 0) {
bdplus_free(plus);
return NULL;
}
}
DEBUG(DBG_BDPLUS, "[bdplus] loading flash.bin...\n");
_load_slots(plus);
memcpy(plus->volumeID, vid, sizeof(plus->volumeID));
......@@ -147,6 +174,14 @@ bdplus_t *bdplus_init(const char *path, const char *config_path, const uint8_t *
return plus;
}
void bdplus_set_fopen(bdplus_t *plus, void *handle, BDPLUS_FILE_OPEN p)
{
if (plus) {
plus->config->fopen_handle = handle;
plus->config->fopen = p;
}
}
void bdplus_set_mk(bdplus_t *plus, const uint8_t *mk)
{
if (plus && mk) {
......@@ -160,6 +195,10 @@ int32_t bdplus_start(bdplus_t *plus)
if (!plus) return -1;
if (!plus->loaded && !_load_svm(plus)) {
return -1;
}
bd_mutex_lock(plus->mutex);
DEBUG(DBG_BDPLUS, "[bdplus] running VM for conv_table...\n");
......@@ -305,6 +344,10 @@ static int32_t _bdplus_event(bdplus_t *plus, uint32_t event, uint32_t param1, ui
{
if (!plus) return -1;
if (!plus->loaded && _load_svm(plus) < 0) {
return -1;
}
if (event == BDPLUS_EVENT_START) {
return bdplus_start(plus);
}
......
......@@ -22,6 +22,8 @@
#include "util/attributes.h"
#include "file/filesystem.h"
#include <stdint.h>
......@@ -70,6 +72,9 @@ typedef struct bdplus_aes_key_s {
typedef struct bdplus_config_s {
void *fopen_handle;
BDPLUS_FILE_OPEN fopen;
bdplus_ram_t *ram; /* mapped player memory */
bdplus_dev_t *dev;
bdplus_ecdsa_key_t *ecdsa_keys;
......
......@@ -56,6 +56,7 @@ struct bdplus_s {
struct bd_mutex_s *mutex;
uint8_t loaded;
uint8_t started;
/* BD+ content code version */
......
......@@ -757,7 +757,7 @@ void interface_trap(VM *vm, uint32_t trap)
else {
result =
TRAP_LoadContentCode(
bdplus_getDevicePath(plus),
bdplus_getConfig(plus),
&vm->addr[ src & ADDR_MASK1 ],// ContentCode
FETCH4( SP+4 ), // block
FETCH4( SP+8 ), // offset
......@@ -811,7 +811,7 @@ void interface_trap(VM *vm, uint32_t trap)
else {
result =
TRAP_MediaCheck(
bdplus_getDevicePath(plus),
bdplus_getConfig(plus),
&vm->addr[ src & ADDR_MASK1 ],// fname
fname_len,
FETCH4( SP+8 ), // OffsHigh
......
......@@ -22,11 +22,11 @@
#include "dlx.h"
#include "file/file.h"
#include "util/logging.h"
#include "util/macro.h"
#include "util/strutl.h"
#include <errno.h>
#include <string.h>
......@@ -85,33 +85,19 @@ static int _code_version_check(uint8_t *hdr, int *p_gen, int *p_date)
return 0;
}
int32_t loader_load_svm(VM *vm, const char *device_path, const char *fname,
int *p_gen, int *p_date)
int32_t loader_load_svm(BDPLUS_FILE_H *fp, const char *fname, VM *vm, int *p_gen, int *p_date)
{
FILE *fd;
uint32_t len;
char *name;
uint8_t *addr = dlx_getAddr(vm);
// Join the path.
name = str_printf("%s/%s", device_path, fname);
// FIXME: Change to Unified FILE functions
fd = fopen(name, "rb");
X_FREE(name);
if (!fd) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error opening %s/%s\n", device_path, fname);
return errno;
}
// Read BD SVM header
if (fread(addr, 0x18, 1, fd) != 1) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error reading header from %s/%s\n", device_path, fname);
return errno;
if (file_read(fp, addr, 0x18) != 0x18) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error reading header from %s\n", fname);
return -1;
}
if (memcmp(addr, "BDSVM_CC", 8)) {
DEBUG(DBG_BDPLUS | DBG_CRIT,"[bdplus] %s/%s failed signature match\n", device_path, fname);
DEBUG(DBG_BDPLUS | DBG_CRIT,"[bdplus] %s failed signature match\n", fname);
}
_code_version_check(addr, p_gen, p_date);
......@@ -122,17 +108,17 @@ int32_t loader_load_svm(VM *vm, const char *device_path, const char *fname,
DEBUG(DBG_BDPLUS,"[bdplus] svm size %08X (%u)\n", len, len);
if (len >= dlx_getAddrSize(vm)) {
DEBUG(DBG_BDPLUS | DBG_CRIT,"[bdplus] Section too long (%d) in %s/%s\n", len, device_path, fname);
DEBUG(DBG_BDPLUS | DBG_CRIT,"[bdplus] Section too long (%d) in %s\n", len, fname);
return -1;
}
// read length data
if (fread(addr, len, 1, fd) != 1) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error reading section from %s/%s\n", device_path, fname);
return errno;
if (file_read(fp, addr, len) != len) {
DEBUG(DBG_BDPLUS | DBG_CRIT, "[bdplus] Error reading section from %s\n", fname);
return -1;
}
fclose(fd);
file_close(fp);
DEBUG(DBG_BDPLUS,"[bdplus] loaded core '%s'\n", fname);
......
......@@ -26,8 +26,8 @@
#include <stdint.h>
struct VM_s;
struct bdplus_file;
BD_PRIVATE int32_t loader_load_svm ( struct VM_s *vm, const char *device_path, const char *fname,
int *p_gen, int *p_date);
BD_PRIVATE int32_t loader_load_svm (struct bdplus_file *fp, const char *fname, struct VM_s *vm, int *p_gen, int *p_date);
#endif
......@@ -22,11 +22,6 @@
#include "config.h"
#endif
#if defined(__MINGW32__)
/* ftello64() and fseeko64() prototypes from stdio.h */
# undef __STRICT_ANSI__
#endif
#include "trap.h"
#include "trap_helper.h"
#include "diff.h"
......@@ -34,11 +29,11 @@
#include "libbdplus/bdplus_config.h"
#include "file/file.h"
#include "util/logging.h"
#include "util/macro.h"
#include "util/strutl.h"
#include <gcrypt.h>
#include <inttypes.h>
......@@ -50,10 +45,6 @@
#include <sys/time.h>
#endif
#if defined(__MINGW32__)
# define fseeko fseeko64
#endif
/* Set this in CFLAGS to debug gcrypt MPIs and S-expressions */
#ifndef GCRYPT_DEBUG
#define GCRYPT_DEBUG 0
......@@ -1159,52 +1150,50 @@ uint32_t TRAP_Discovery(bdplus_config_t *config, uint32_t dev, uint32_t qID, uin
//
// Filename "00001" -> "BDSVM/00001.svm".
//
uint32_t TRAP_LoadContentCode(const char *device_path, uint8_t *FileName, uint32_t Section, uint32_t Unknown, uint32_t *len, uint8_t *dst)
uint32_t TRAP_LoadContentCode(bdplus_config_t *config, uint8_t *FileName, uint32_t Section, uint32_t Unknown, uint32_t *len, uint8_t *dst)
{
FILE *fd;
BDPLUS_FILE_H *fd;
int64_t rbytes;
uint8_t *fname;
char *fname;
DEBUG(DBG_BDPLUS_TRAP,"[TRAP] TRAP_LoadContentCode('%s':%08X -> %p)\n", FileName, *len, dst);
// Build the real filename.
fname = (uint8_t *)
str_printf("%s/BDSVM/%s.svm",
device_path,
(char *) FileName);
fname = str_printf("BDSVM/%s.svm", (char *) FileName);
DEBUG(DBG_BDPLUS,"[TRAP] reading '%s': unknown %08X\n", fname, Unknown);
fd = fopen((char *)fname, "rb");
fd = file_open(config, fname);
X_FREE(fname);
if (!fd) {
DEBUG(DBG_BDPLUS | DBG_CRIT,"[TRAP] ERROR: cant open %s\n", (char*)FileName);
return STATUS_INVALID_PARAMETER; // FIXME
}
// Skip the SVM header.
if (fseek(fd, SVM_HEADER_SIZE, SEEK_SET) < 0) {
if (file_seek(fd, SVM_HEADER_SIZE, SEEK_SET) < 0) {
DEBUG(DBG_BDPLUS | DBG_CRIT,"[TRAP] ERROR: seeking %s (header) failed\n", (char*)FileName);
fclose(fd);
file_close(fd);
return STATUS_INVALID_PARAMETER;
}
if (fseek(fd, Section * 0x200000, SEEK_CUR) < 0) { // locate wanted section
if (file_seek(fd, Section * 0x200000, SEEK_CUR) < 0) { // locate wanted section
DEBUG(DBG_BDPLUS | DBG_CRIT,"[TRAP] ERROR: seeking %s to section %d failed\n", (char*)FileName, Section);
fclose(fd);
file_close(fd);
return STATUS_INVALID_PARAMETER;
}
// They assume the memory wraps, and sometimes deliberately load near the
// end of the memory.
DEBUG(DBG_BDPLUS,"[TRAP] reading %d/%08X bytes into %p\n", *len, *len, dst);
rbytes = fread(dst, 1, *len, fd);
rbytes = file_read(fd, dst, *len);
if (rbytes < 0 || rbytes != (int64_t)*len) {
DEBUG(DBG_BDPLUS | DBG_CRIT,"[TRAP] ERROR: read %"PRId64" bytes of %d from %s\n", rbytes, *len, (char*)FileName);
fclose(fd);
file_close(fd);
return STATUS_INVALID_PARAMETER;
}
fclose(fd);
file_close(fd);
DEBUG(DBG_BDPLUS,"[TRAP] read %"PRId64" bytes. %p-%p\n", rbytes, dst, &dst[rbytes]);
*len = rbytes;
......@@ -1270,25 +1259,15 @@ uint32_t TRAP_DiscoveryRAM(bdplus_config_t *config, uint32_t src, uint8_t *buffe
return STATUS_OK;
}
uint32_t TRAP_MediaCheck(const char *device_path, uint8_t *FileName, uint32_t FileNameLen, uint32_t FileOffsetHigh, uint32_t FileOffsetLow, uint32_t *len, uint8_t *dst)
uint32_t TRAP_MediaCheck(bdplus_config_t *config, uint8_t *FileName, uint32_t FileNameLen, uint32_t FileOffsetHigh, uint32_t FileOffsetLow, uint32_t *len, uint8_t *dst)
{
uint8_t buffer[SHA_BLOCK_SIZE]; // fix me
FILE *fd;
BDPLUS_FILE_H *fd;
uint32_t j;
uint64_t seek;
uint8_t *full_name;
DEBUG(DBG_BDPLUS_TRAP,"[TRAP] TRAP_MediaCheck(%d/%d)\n", *len, FileNameLen);
// Build the real filename.
full_name = (uint8_t *)
str_printf("%s/%s",