📄 iso9660.c
字号:
/*****************************************************************************//* *//* <C> STMicroelectronics - copyright information *//* *//* *//* COMMENT }DOCUMENTATION *//* File Name :: iso9660.c *//* Creation Date :: September 2005 *//* Author :: Ondrej Trubac *//* Version :: $Revision: 1.25 $ *//* Last change :: $Date: 2007/06/01 14:09:54 $ by $Author: trubac $ *//* Description :: ISO9660 detection/handling *//* } *//*****************************************************************************//*************************************************** * * COPYRIGHT (C) ST Microelectronics 2005 * All Rights Reserved * ******************************************************************************* * \brief Player * * \par Change History: * * - BB060626 Fixed ISO9660 parsing (directory record larger than sector) * - BB060929a Improved no TOC and Copyprotected CD support * **************************************************** * * STM CVS Log: * * $Log: ISO9660.c,v $ * Revision 1.25 2007/06/01 14:09:54 trubac * Update HEAD by changes from B_3_1_P3 (1.20.2.3) * * Revision 1.24 2007/05/02 12:31:41 belardi * Removed unused variable * * Revision 1.23 2007/03/28 17:09:42 trubac * workaround for variable length character encoding (Asian standards) * * Revision 1.22 2007/03/13 13:05:22 trubac * boot record ignored when ISO9660 detected * * Revision 1.20 2006/11/17 16:36:14 dellorto * added copy of PVD address for hostif read TOC message * * Revision 1.19 2006/10/17 09:59:27 trubac * ISO_Detect cosmetic rearangement + copy protected CD support * * Revision 1.18 2006/09/18 09:55:22 belardi * Corrected CVS keyword usage * * Revision 1.17 2006/09/18 09:24:02 belardi * Added Log CVS keyword into file header * * ******************************************************************************/#include <stdio.h>#include <stdlib.h>// #include <conio.h> used for PC when _getch needed#include <string.h>#include "gendef.h"#include "accordoptypes.h" //"aptypes.h"#include "apdevsys.h"#include "iso9660.h"#include "cddevice.h"#include "bytestream.h"#include "debug.h"#include "utf8.h"#include "xfile.h"#include "filesys.h"#include "capture.h"#include "controller.h"#include "hostif_high.h"#if (ISO_DEBUG != 0)#define ISOPRINTF(...) dprintf(__VA_ARGS__)#else//#define ISOPRINTF(x)#define ISOPRINTF(...) do{}while(0)#endif#define SECTOR_SIZE 2048GRESULT ISO_GetDirItem(SCAN_STRUCT *scans, DIR_ITEM *item, uint8 *buf){ FS_DESCRIPTOR *fsd; uint8 *tbuf; uint16 position; int i; uint32 offset; uint8 p; GRESULT res; t_conv_param pp; t_lba slba; int tmp1,j; uint8 *cp; uint16 wc;//static GRESULT debug_error; fsd = scans->fs_descriptor; if (!scans->DirRecordOffset) { slba = 150 + fsd->PartitionLBA + scans->DirRecordLba; ISOPRINTF("ISO_GetDirItem1 LBA: %d\n", slba); PREPARE_IOREAD(FS_XFER_command_event, DEV_CD_ID, slba, slba, 0, SECTOR_SIZE, buf, SECTOR_SIZE, IO_READ_IMMEDIATE); if (0 > (res = IO_Read(IO_READ_IMMEDIATE))) { //debug_error = res+1; return res; } scans->DirRecordLength = BYTEREAD32(buf, 14); p = *buf; scans->DirRecordOffset = p + buf[p]; scans->OffsetSectors = 0; // check of directory LBA, should match with directory extent position slba = BYTEREAD32(buf,6); if(slba!=scans->DirRecordLba) {// debug_error = E_FS_INTEGRITY_ERROR; return E_FS_INTEGRITY_ERROR; } if(buf[25]&2) { if(buf[32]>2) { // debug_error = E_UNEXPECTED; return E_UNEXPECTED; } } else {// debug_error = E_UNKNOWN_FS_TYPE; return E_UNKNOWN_FS_TYPE; } } if( (!(scans->DirRecordOffset%SECTOR_SIZE))&&(scans->DirRecordOffset!=SECTOR_SIZE*scans->OffsetSectors)) { scans->OffsetSectors++; slba = 150 + fsd->PartitionLBA + scans->OffsetSectors + scans->DirRecordLba; ISOPRINTF("ISO_GetDirItem3 LBA: %d\n", slba); PREPARE_IOREAD(FS_XFER_command_event, DEV_CD_ID, slba, slba, 0, SECTOR_SIZE, buf, SECTOR_SIZE, IO_READ_IMMEDIATE); if (0 > (res = IO_Read(IO_READ_IMMEDIATE))) { //debug_error = res+2; return res; } } skip_nulls: if (scans->DirRecordOffset >= scans->DirRecordLength) return S_NOT_FOUND; position = scans->DirRecordOffset % SECTOR_SIZE; //zero_check: p = buf[position]; if (!p) { scans->OffsetSectors++; scans->DirRecordOffset = SECTOR_SIZE * scans->OffsetSectors; slba = 150 + fsd->PartitionLBA + scans->OffsetSectors + scans->DirRecordLba; ISOPRINTF("ISO_GetDirItem2 LBA: %d\n", slba); PREPARE_IOREAD(FS_XFER_command_event, DEV_CD_ID, slba, slba, 0, SECTOR_SIZE, buf, SECTOR_SIZE, IO_READ_IMMEDIATE); if (0 > (res = IO_Read(IO_READ_IMMEDIATE))) { //debug_error = res+3; return res; } goto skip_nulls; } tbuf = &buf[position]; offset = scans->DirRecordOffset; scans->DirRecordOffset += p; if ((position + p) > SECTOR_SIZE) /* BB060929a */ { return E_WRONG_FORMAT; } if (tbuf[25] & 2) { item->dir.DirRecordLba = BYTEREAD32(tbuf, 6); item->dir.ParentOffset = offset; if (!scans->byte0) { memcpy(item->dir.Name, tbuf + 33, tbuf[32]); item->dir.NameLength = tbuf[32]; } else { pp.be = 1; pp.trunc = 0; pp.limit = 255; item->dir.NameLength = WideStringToUTF8(tbuf + 33, item->dir.Name, tbuf[32] >> 1, &pp); if(item->dir.NameLength<0) { return E_WRONG_FORMAT; } } return S_DIR_FOUND; } // else this is file item->file.DirRecordLba = scans->DirRecordLba; item->file.DirRecordOffset = offset; item->file.ExtentLba = BYTEREAD32(tbuf, 6); item->file.FileSize = BYTEREAD32(tbuf, 14); p = tbuf[32]; // length of identifier if ((position + p) > SECTOR_SIZE) /* BB060929a */ { return E_WRONG_FORMAT; } tmp1 = j = 0; // check ';' and UCS-2 for (i = p - 1; i >= 0; i--) { if (!tbuf[33 + i]) tmp1 = 1; if ((!j)&&(tbuf[33 + i] == 0x3B)) { j = i; break; } } if(j && scans->byte0) { if(tmp1) // check if name is UCS-2 encoded j--; } i = j; if (i <= 1) { i = p; // real name length //return E_WRONG_FORMAT; } if (tbuf[33 + i - 1] == 0x2E) { return S_FILE_SKIP; } p = i; if (scans->byte0) { pp.be = 1; pp.trunc = 0; pp.limit = 250; if(tmp1) { item->file.NameLength = WideFileNameToUTF8(tbuf + 33, item->file.Name, i >> 1, &pp); if(item->file.NameLength<0) { return E_WRONG_FORMAT; } } else { // characters are not UCS-2, but kind of multibyte encoding, like GB2312,GBK,... cp = item->file.Name; i = 0; tmp1 = 0; do { wc = 0; if(tbuf[33+i]>=128) { wc = tbuf[33+i] << 8; i++; } wc += tbuf[33+i]; i++; tmp1 += wc2utf8(wc,&cp); // convert character to UTF-8 sequence }while(i<p); item->file.NameLength = tmp1; } } else { item->file.NameLength = i; memcpy(item->file.Name, tbuf + 33, i); } return S_FILE_FOUND;}/*************************************************************************/GRESULT ISO_Detect(DUID cdid, int partition, FS_DESCRIPTOR *fsd){ CD_DeviceDescriptor *cddesc; int err; int32 res; uint8 cbuf[256]; uint32 volumeDescriptorLba; PRIVATE_DATA_ISO9660 *isod; if (SYS_DeviceType(cdid) != DEV_CD_ID) { return E_INVALID_DEVICE_TYPE; } hostif_pvd_address = 0xFFFFFFFF; cddesc = (CD_DeviceDescriptor *) SYS_DeviceDescriptor(cdid); if (NULL == (void *) cddesc) { return E_INVALID_DEVICE_DESCRIPTOR; } fsd->attributes = 0; isod = &fsd->PD.ISO_pd; res = CD_LastSessionLBA(); if (res < 0) return E_NO_FS_CARRIER; /* BB060929a */ isod->IsoVolumeLba = res + 16 - TOC_OFFSET_SECTOR; // Unless noted otherwise every lba is considered to be without 2 seconds offset // for requesting from CD, value lba+150 must be used // now check if ISO9660 Primary Volume Descriptor and Joliet descriptor is present volumeDescriptorLba = isod->IsoVolumeLba; // reset device flags according detection method#if 0 if (flags & ISO_DETECT_PRIMARY_DESCRIPTOR_ONLY) { SYS_ClearDeviceAttribute(cdid, DEV_ATTR_ISO_PRIMARY_VOL_DESCRIPTOR); } else { if (flags & ISO_DETECT_SUPPLEM_DESCRIPTOR_ONLY) SYS_ClearDeviceAttribute(cdid, DEV_ATTR_ISO_SUPPLEM_VOL_DESCRIPTOR); else SYS_ClearDeviceAttribute(cdid, DEV_ATTR_ISO9660_FILESYSTEM); }#else SYS_ClearDeviceAttribute(cdid, DEV_ATTR_ISO9660_FILESYSTEM);#endif //cbuf = (uint8*)malloc(256); isod->PrimaryDescriptorLba = 0; isod->SupplementaryDescriptorLba = 0; isod->IsoDescriptorLba = 0; fsd->LargeBlockSize = SECTOR_SIZE; fsd->Partition = partition; fsd->PartitionLBA = SYS_PartitionLBA(cdid, partition, SECTOR_SIZE); fsd->FSType = FS_ISO9660_TYPE; fsd->did = cdid; do { ISOPRINTF("ISO_Detect LBA: %d\n", 150 + fsd->PartitionLBA + volumeDescriptorLba); PREPARE_IOREAD(FS_XFER_command_event, DEV_CD_ID, 150 + fsd->PartitionLBA + volumeDescriptorLba, 150 + fsd->PartitionLBA + volumeDescriptorLba, 0, SECTOR_SIZE, cbuf, 256, IO_READ_IMMEDIATE); err = IO_Read(IO_READ_IMMEDIATE); if (err < 0) { return err; } if (cbuf[0] == 0) { //free(cbuf); //return S_FALSE; can cause problem when boot record found } if (cbuf[0] == 1) // PRIMARY VOLUME DESCRIPTOR { if (!strncmp("CD001", (char *) cbuf + 1, 5)) { SYS_SetDeviceAttribute(cdid,DEV_ATTR_ISO9660_FILESYSTEM|DEV_ATTR_ISO_PRIMARY_VOL_DESCRIPTOR); isod->PrimaryDescriptorLba = volumeDescriptorLba; #if 0 // optional selection of volume descriptors if(flags&ISO_DETECT_PRIMARY_DESCRIPTOR_ONLY) { isod->IsoDescriptorLba = volumeDescriptorLba; fsd->attributes &=(MAX_UINT_VALUE-ISO9660_SUPPLEM_VOL_DESCRIPTOR_FLAG); break; } #endif volumeDescriptorLba++; continue; } } if (cbuf[0] == 2) // SUPPLEMENTARY VOLUME DESCRIPTOR { if (!strncmp("CD001", (char *) cbuf + 1, 5)) { SYS_SetDeviceAttribute(cdid, DEV_ATTR_ISO9660_FILESYSTEM|DEV_ATTR_ISO_SUPPLEM_VOL_DESCRIPTOR); isod->SupplementaryDescriptorLba = volumeDescriptorLba; #if 0 // optional descriptor selection if(flags&ISO_DETECT_SUPPLEM_DESCRIPTOR_ONLY) { isod->IsoDescriptorLba = volumeDescriptorLba; fsd->attributes |= ISO9660_SUPPLEM_VOL_DESCRIPTOR_FLAG; break; } #endif volumeDescriptorLba++; continue; } } volumeDescriptorLba++; } while ((volumeDescriptorLba < (isod->IsoVolumeLba + 10)) && (cbuf[0] != 255)); // VOLUMEDESCRIPTORSETTERMINATOR) // -see-iso9660-8.1.1 if(!isod->IsoDescriptorLba) { /* this option is not included if(flags&(ISO_DETECT_PRIMARY_DESCRIPTOR_ONLY|ISO_DETECT_SUPPLEM_DESCRIPTOR_ONLY)) { return S_FALSE; } */ if(isod->SupplementaryDescriptorLba) { isod->IsoDescriptorLba=isod->SupplementaryDescriptorLba; fsd->attributes |= ISO9660_SUPPLEM_VOL_DESCRIPTOR_FLAG; } else { if(isod->PrimaryDescriptorLba) { isod->IsoDescriptorLba=isod->PrimaryDescriptorLba; fsd->attributes &= (MAX_UINT_VALUE-ISO9660_SUPPLEM_VOL_DESCRIPTOR_FLAG); } else return S_FALSE; } } hostif_pvd_address = isod->IsoDescriptorLba + 150;// Now ISO descriptor lba is set err=ISO_GetDiscInfo(fsd,cbuf); if(err<0) return err; return S_TRUE;}/*************************************************************************/GRESULT ISO_GetDiscInfo(FS_DESCRIPTOR *cdd, uint8 *buf){ int position; uint8 *ptr; unsigned int lbaDiskSize; unsigned int sectorSize; GRESULT err; t_conv_param p;// err=IO_Read(cdd->did,cdd->PartitionLBA+cdd->PD.ISO_pd.IsoDescriptorLba,0,2048,buf,256,CD_FAIL_ON_READ_TIMEOUT); PREPARE_IOREAD(FS_XFER_command_event,DEV_CD_ID,150+cdd->PartitionLBA+cdd->PD.ISO_pd.IsoDescriptorLba,150+cdd->PartitionLBA+cdd->PD.ISO_pd.IsoDescriptorLba,0,2048,buf,256,IO_READ_IMMEDIATE); err=IO_Read(IO_READ_IMMEDIATE); if(err<0) { return err; } position = VOLUMENAME_POS; ptr = cdd->VolumeName; /* prepare data for joliet cd type */ if (cdd->attributes & ISO9660_SUPPLEM_VOL_DESCRIPTOR_FLAG) // test if Joliet { p.be = 1; p.trunc = 0; p.limit = 32; cdd->VolumeNameLength = WideStringToUTF8(buf + position, ptr, 16, &p); } else { cdd->VolumeNameLength = 11; memcpy(ptr, buf + position, 11); } /* extract lba cd disk size */ lbaDiskSize = BYTEREAD24(buf, VOLUMESPACESIZE_POS); /* extract sector size */ sectorSize = BYTEREAD16(buf, LOGICALBLOCKSIZE_POS); cdd->PD.ISO_pd.DiscSize = ((unsigned long) lbaDiskSize) * ((unsigned long) sectorSize); cdd->PD.ISO_pd.PathTableLba = BYTEREAD24(buf, PATHTABLELBA_POS); cdd->PD.ISO_pd.PathTableLength = BYTEREAD24(buf, PATHTABLESIZE_POS); cdd->PD.ISO_pd.RootRecordLba = BYTEREAD24(buf, ROOTDIRLBA_POS); DEBUG_LOG("PathTable LBA : %d\n", cdd->PD.ISO_pd.PathTableLba) DEBUG_LOG("PathTable length : %d\n", cdd->PD.ISO_pd.PathTableLength) DEBUG_LOG("RootRecordLba : %d\n", cdd->PD.ISO_pd.RootRecordLba) return S_OK;}/*************************************************************************//*****************************************************************/#if 0 // [RB] commented out to reduce ROM spaceuint8 ISO_ExtensionCheck(FILE_STRUCT *file, char *ex){ return 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -