Import Upstream version 7.1

This commit is contained in:
openKylinBot 2022-05-23 18:36:28 +08:00
commit 94ad998944
20 changed files with 14797 additions and 0 deletions

339
LICENSE Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

46
Makefile Normal file
View File

@ -0,0 +1,46 @@
all:
@(m4 -DOS=`uname -s` Makefile.m4 | $(MAKE) -f - dvd+rw-tools)
install:# BSD make doesn't support wild-card targets:-(
@(m4 -DOS=`uname -s` Makefile.m4 | $(MAKE) -f - $@)
nothing:# dumb target
.%: # don't mess with Solaris .INIT/.DONE, ...
%: # ... but the rest just passes through
@(m4 -DOS=`uname -s` Makefile.m4 | $(MAKE) -f - $@)
CHAIN=growisofs dvd+rw-format dvd+rw-booktype dvd+rw-mediainfo dvd-ram-control
clean:
-(rm *.o $(CHAIN) rpl8 btcflash panaflash; exit 0) < /dev/null > /dev/null 2>&1
VER=7.1
DIST=dvd+rw-tools-$(VER)
pkg:
[ -h $(DIST) ] || ln -s . $(DIST)
tar chf dvd+rw-tools-$(VER).tar \
--owner=bin --group=bin \
$(DIST)/Makefile \
$(DIST)/Makefile.m4 \
$(DIST)/dvd+rw-tools.spec \
$(DIST)/growisofs.1 \
$(DIST)/transport.hxx \
$(DIST)/mp.h \
$(DIST)/win32err.h \
$(DIST)/keys.txt \
$(DIST)/genasctable.pl \
$(DIST)/asctable.h \
$(DIST)/growisofs.c \
$(DIST)/growisofs_mmc.cpp \
$(DIST)/dvd+rw-format.cpp \
$(DIST)/dvd+rw-mediainfo.cpp \
$(DIST)/dvd+rw-booktype.cpp \
$(DIST)/dvd-ram-control.cpp \
$(DIST)/rpl8.cpp \
$(DIST)/btcflash.cpp \
$(DIST)/LICENSE
if [ -f index.html ]; then \
tar rhf dvd+rw-tools-$(VER).tar \
--owner=bin --group=bin \
$(DIST)/index.html; \
fi
gzip -f dvd+rw-tools-$(VER).tar
rm $(DIST)

240
Makefile.m4 Normal file
View File

@ -0,0 +1,240 @@
# OBS! M4 processed!
changequote([, ])
[
CHAIN=growisofs dvd+rw-format dvd+rw-booktype dvd+rw-mediainfo dvd-ram-control
dvd+rw-tools: $(CHAIN)
WARN=#-Wall # developers are welcomed to build with `make WARN=-Wall'
]
# fix-up OS macro
ifelse(substr(OS,0,7),[CYGWIN_],[define([OS],[MINGW32])])
ifelse(substr(OS,0,7),[MINGW32],[define([OS],[MINGW32])])
ifelse(OS,NetBSD,[define([OS],[BSD])CXXFLAGS+=-D__unix])
ifelse(OS,OpenBSD,[define([OS],[BSD])])
ifelse(OS,FreeBSD,[define([OS],[BSD])LDLIBS=-lcam])
ifelse(OS,IRIX64,[define([OS],[IRIX])])
ifelse(OS,Darwin,[
#
# Mac OS X section
#
CC =gcc
CFLAGS +=$(WARN) -D__unix -O2
CXX =g++
CXXFLAGS+=$(WARN) -D__unix -O2 -fno-exceptions
LDLIBS =-framework CoreFoundation -framework IOKit
LINK.o =$(LINK.cc)
# to install set-root-uid, `make BIN_MODE=04755 install'...
BIN_MODE?=0755
install: dvd+rw-tools
install -o root -m $(BIN_MODE) $(CHAIN) /usr/bin
install -o root -m 0644 growisofs.1 /usr/share/man/man1
])
ifelse(OS,MINGW32,[
#
# MINGW section
#
CC =gcc
CFLAGS +=$(WARN) -mno-cygwin -O2
CXX =g++
CXXFLAGS+=$(WARN) -mno-cygwin -O2 -fno-exceptions
LINK.o =$(LINK.cc)
])
ifelse(OS,BSD,[
#
# OpenBSD/NetBSD/FreeBSD section
#
CC ?=gcc
CFLAGS +=$(WARN) -O2 -pthread -D_THREAD_SAFE -D_REENTRANT
CXX ?=g++
CXXFLAGS+=$(WARN) -O2 -fno-exceptions -pthread -D_THREAS_SAFE -D_REENTRANT
.SUFFIXES: .c .cpp .o
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
.o: # try to please both BSD vv&vv GNU make at the same time...
$(CXX) $(CXXFLAGS) -o $@ $> $^ $(LDFLAGS) $(LDLIBS)
# yes, default is set-root-uid, `make BIN_MODE=0755 install' to override...
BIN_MODE?=04755
install: dvd+rw-tools
install -o root -m $(BIN_MODE) $(CHAIN) /usr/local/bin
install -o root -m 0644 growisofs.1 /usr/local/man/man1
])
ifelse(OS,SunOS,[
#
# Solaris section
#
.SUFFIXES: .c .cpp .o
# check for WorkShop C++
syscmd([(CC -flags) > /dev/null 2>&1])
ifelse(sysval,0,[
CC =cc
CFLAGS =-O -xstrconst -w -D_REENTRANT -D__`uname -s`=`uname -r | tr -d .`
CXX =CC
CXXFLAGS=-O -features=no%except,conststrings -w -D_REENTRANT
LDFLAGS =-staticlib=%all
],[
CC =gcc
CFLAGS =$(WARN) -O2 -D_REENTRANT -D__`uname -s`=`uname -r | tr -d .`
CXX =g++
CXXFLAGS=$(WARN) -O2 -fno-exceptions -D_REENTRANT
])
LDLIBS=-lvolmgt -lrt -lpthread -ldl
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
%: %.o
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS)
install: dvd+rw-tools
/usr/ucb/install -o root -m 04755 $(CHAIN) /usr/local/bin
/usr/ucb/install -o root -m 0644 growisofs.1 /usr/local/man/man1
])
ifelse(OS,HP-UX,[
#
# HP-UX section
#
.SUFFIXES: .c .cpp .o
# check for HP C++
syscmd([(aCC -E /dev/null) > /dev/null 2>&1])
ifelse(sysval,0,[
# run `make TARGET_ARCH=+DD64' for 64-bit build...
# ... or should we check for `getconf KERNEL_BITS' and/or CPU_VERSION?
# syscmd([([ `getconf KERNEL_BITS` -eq 64 ]) > /dev/null 2>&1])
CC =cc
CFLAGS =$(TARGET_ARCH) -O -D_REENTRANT
CXX =aCC
CXXFLAGS=$(TARGET_ARCH) -O +noeh -D_REENTRANT
],[
CC =gcc
CFLAGS =$(WARN) -O2 -D_REENTRANT
CXX =g++
CXXFLAGS=$(WARN) -O2 -fno-exceptions -D_REENTRANT
])
LDLIBS=-lrt -lpthread
.c.o:
$(CC) $(CFLAGS) \
-DSCTL_MAJOR=`/usr/sbin/lsdev -h -d sctl | awk '{print$$1}'` \
-c -o $@ $<
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
.o: # try to please both BSD vv&vv GNU make at the same time...
$(CXX) $(CXXFLAGS) -o $@ $> $^ $(LDFLAGS) $(LDLIBS)
install: dvd+rw-tools
/usr/sbin/install -o -f /usr/local/bin $(CHAIN)
/usr/sbin/install -o -f /usr/local/man/man1 growisofs.1
])
ifelse(OS,IRIX,[
#
# IRIX section
#
.SUFFIXES: .c .cpp .o
# check for MIPSpro compiler
syscmd([(CC -version) > /dev/null 2>&1])
ifelse(sysval,0,[
CC =cc
CFLAGS =$(WARN) -O -use_readonly_const -D_SGI_MP_SOURCE
CXX =CC
CXXFLAGS=$(WARN) -O -OPT:Olimit=0 -use_readonly_const -LANG:exceptions=OFF -D_SGI_MP_SOURCE
],[
CC =gcc
CFLAGS =$(WARN) -O2 -D_SGI_MP_SOURCE
CXX =g++
CXXFLAGS=$(WARN) -O2 -fno-exceptions -D_SGI_MP_SOURCE
])
LDLIBS=-lmediad -lpthread
LDFLAGS=-dont_warn_unused
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
.o:
$(CXX) $(CXXFLAGS) -o $@ $> $^ $(LDFLAGS) $(LDLIBS)
BIN_MODE=04755 # set-root-uid
install: dvd+rw-tools
/sbin/install -u root -m $(BIN_MODE) $(CHAIN) /usr/local/bin
/sbin/install -u root -m 0644 growisofs.1 /usr/local/man/man1
])
ifelse(OS,Linux,[
#
# Linux section
#
CC =gcc
CFLAGS +=$(WARN) -O2 -D_REENTRANT
CXX =g++
CXXFLAGS+=$(WARN) -O2 -fno-exceptions -D_REENTRANT
LDLIBS =-lpthread
LINK.o =$(LINK.cc)
prefix?=/usr/local
manprefix?=$(shell case $(prefix) in (*/usr/?*) echo $(prefix)/man ;; (*) echo $(prefix)/share/man ;; esac)
bin_mode?=0755 # yes, default is *no* set-uid
minus_o:=$(shell [[ `id -u` == 0 ]] && echo "-o root")
install: dvd+rw-tools
[[ -d $(prefix)/bin ]] || mkdir -p $(prefix)/bin
install $(minus_o) -m $(bin_mode) $(CHAIN) $(prefix)/bin
[[ -d $(manprefix)/man1 ]] || mkdir -p $(manprefix)/man1
install $(minus_o) -m 0644 growisofs.1 $(manprefix)/man1
-[[ -f rpl8 ]] && install $(minus_o) -m $(bin_mode) rpl8 $(prefix)/bin; :
-[[ -f btcflash ]] && install $(minus_o) -m $(bin_mode) btcflash $(prefix)/bin; :
])
# common section
[
growisofs: growisofs_mmc.o growisofs.o
growisofs.o: growisofs.c mp.h
growisofs_mmc.o: growisofs_mmc.cpp transport.hxx asctable.h
asctable.h: keys.txt
perl genasctable.pl < keys.txt > $@
dvd+rw-format: dvd+rw-format.o
dvd+rw-format.o: dvd+rw-format.cpp transport.hxx asctable.h
dvd+rw-mediainfo: dvd+rw-mediainfo.o
dvd+rw-mediainfo.o: dvd+rw-mediainfo.cpp transport.hxx asctable.h
dvd+rw-booktype: dvd+rw-booktype.o
dvd+rw-booktype.o: dvd+rw-booktype.cpp transport.hxx asctable.h
dvd-ram-control: dvd-ram-control.o
dvd-ram-control.o: dvd-ram-control.cpp transport.hxx asctable.h
rpl8: rpl8.o
rpl8.o: rpl8.cpp transport.hxx asctable.h
+rpl8: rpl8
#so that I can invoke `make +rpl8' to build rpl8...
btcflash: btcflash.o
btcflash.o: btcflash.cpp transport.hxx asctable.h
+btcflash: btcflash
#so that I can invoke `make +btcflash' to build btcflash...
panaflash: panaflash.o
panaflash.o: panaflash.cpp transport.hxx asctable.h
+panaflash: panaflash
]

250
asctable.h Normal file
View File

@ -0,0 +1,250 @@
const char *ASC_lookup (int code)
{ static const struct { int code; const char *msg; } _table [] = {
{ 0x0000, "NO ADDITIONAL SENSE INFORMATION" },
{ 0x0006, "I/O PROCESS TERMINATED" },
{ 0x0011, "AUDIO PLAY OPERATION IN PROGRESS" },
{ 0x0012, "AUDIO PLAY OPERATION PAUSED" },
{ 0x0013, "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED" },
{ 0x0014, "AUDIO PLAY OPERATION STOPPED DUE TO ERROR" },
{ 0x0015, "NO CURRENT AUDIO STATUS TO RETURN" },
{ 0x0016, "OPERATION IN PROGRESS" },
{ 0x0017, "CLEANING REQUESTED" },
{ 0x0200, "NO SEEK COMPLETE" },
{ 0x0400, "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE" },
{ 0x0401, "LOGICAL UNIT IS IN PROCESS OF BECOMING READY" },
{ 0x0402, "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED" },
{ 0x0403, "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED" },
{ 0x0404, "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS" },
{ 0x0407, "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS" },
{ 0x0408, "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS" },
{ 0x0409, "LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS" },
{ 0x0500, "LOGICAL UNIT DOES NOT RESPOND TO SELECTION" },
{ 0x0600, "NO REFERENCE POSITION FOUND" },
{ 0x0700, "MULTIPLE PERIPHERAL DEVICES SELECTED" },
{ 0x0800, "LOGICAL UNIT COMMUNICATION FAILURE" },
{ 0x0801, "LOGICAL UNIT COMMUNICATION TIMEOUT" },
{ 0x0802, "LOGICAL UNIT COMMUNICATION PARITY ERROR" },
{ 0x0803, "LOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)" },
{ 0x0900, "TRACK FOLLOWING ERROR" },
{ 0x0901, "TRACKING SERVO FAILURE" },
{ 0x0902, "FOCUS SERVO FAILURE" },
{ 0x0903, "SPINDLE SERVO FAILURE" },
{ 0x0904, "HEAD SELECT FAULT" },
{ 0x0A00, "ERROR LOG OVERFLOW" },
{ 0x0B00, "WARNING" },
{ 0x0B01, "WARNING - SPECIFIED TEMPERATURE EXCEEDED" },
{ 0x0B02, "WARNING - ENCLOSURE DEGRADED" },
{ 0x0B03, "WARNING - BACKGROUND SELF-TEST FAILED" },
{ 0x0B04, "WARNING - BACKGROUND PRE-SCAN DETECTED MEDIUM ERROR" },
{ 0x0B05, "WARNING - BACKGROUND MEDIUM SCAN DETECTED MEDIUM ERROR" },
{ 0x0C00, "WRITE ERROR" },
{ 0x0C01, "WRITE ERROR - RECOVERED WITH AUTO-REALLOCATION" },
{ 0x0C02, "WRITE ERROR - AUTO-REALLOCATION FAILED" },
{ 0x0C03, "WRITE ERROR - RECOMMEND REASSIGNMENT" },
{ 0x0C07, "WRITE ERROR - RECOVERY NEEDED" },
{ 0x0C08, "WRITE ERROR - RECOVERY FAILED" },
{ 0x0C09, "WRITE ERROR - LOSS OF STREAMING" },
{ 0x0C0A, "WRITE ERROR - PADDING BLOCKS ADDED" },
{ 0x0C0F, "DEFECTS IN ERROR WINDOW" },
{ 0x1100, "UNRECOVERED READ ERROR" },
{ 0x1101, "READ RETRIES EXHAUSTED" },
{ 0x1102, "ERROR TOO LONG TO CORRECT" },
{ 0x1105, "L-EC UNCORRECTABLE ERROR" },
{ 0x1106, "CIRC UNRECOVERED ERROR" },
{ 0x110F, "ERROR READING UPC/EAN NUMBER" },
{ 0x1110, "ERROR READING ISRC NUMBER" },
{ 0x1111, "READ ERROR - LOSS OF STREAMING" },
{ 0x1500, "RANDOM POSITIONING ERROR" },
{ 0x1501, "MECHANICAL POSITIONING ERROR" },
{ 0x1502, "POSITIONING ERROR DETECTED BY READ OF MEDIUM" },
{ 0x1700, "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED" },
{ 0x1701, "RECOVERED DATA WITH RETRIES" },
{ 0x1702, "RECOVERED DATA WITH POSITIVE HEAD OFFSET" },
{ 0x1703, "RECOVERED DATA WITH NEGATIVE HEAD OFFSET" },
{ 0x1704, "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED" },
{ 0x1705, "RECOVERED DATA USING PREVIOUS SECTOR ID" },
{ 0x1707, "RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT" },
{ 0x1708, "RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE" },
{ 0x1709, "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN" },
{ 0x1800, "RECOVERED DATA WITH ERROR CORRECTION APPLIED" },
{ 0x1801, "RECOVERED DATA WITH ERROR CORR. & RETRIES APPLIED" },
{ 0x1802, "RECOVERED DATA - DATA AUTO-REALLOCATED" },
{ 0x1803, "RECOVERED DATA WITH CIRC" },
{ 0x1804, "RECOVERED DATA WITH L-EC" },
{ 0x1805, "RECOVERED DATA - RECOMMEND REASSIGNMENT" },
{ 0x1806, "RECOVERED DATA - RECOMMEND REWRITE" },
{ 0x1808, "RECOVERED DATA WITH LINKING" },
{ 0x1A00, "PARAMETER LIST LENGTH ERROR" },
{ 0x1B00, "SYNCHRONOUS DATA TRANSFER ERROR" },
{ 0x1D00, "MISCOMPARE DURING VERIFY OPERATION" },
{ 0x2000, "INVALID COMMAND OPERATION CODE" },
{ 0x2100, "LOGICAL BLOCK ADDRESS OUT OF RANGE" },
{ 0x2101, "INVALID ELEMENT ADDRESS" },
{ 0x2102, "INVALID ADDRESS FOR WRITE" },
{ 0x2103, "INVALID WRITE CROSSING LAYER JUMP" },
{ 0x2200, "ILLEGAL FUNCTION" },
{ 0x2400, "INVALID FIELD IN CDB" },
{ 0x2500, "LOGICAL UNIT NOT SUPPORTED" },
{ 0x2600, "INVALID FIELD IN PARAMETER LIST" },
{ 0x2601, "PARAMETER NOT SUPPORTED" },
{ 0x2602, "PARAMETER VALUE INVALID" },
{ 0x2603, "THRESHOLD PARAMETERS NOT SUPPORTED" },
{ 0x2604, "INVALID RELEASE OF PERSISTENT RESERVATION" },
{ 0x2700, "WRITE PROTECTED" },
{ 0x2701, "HARDWARE WRITE PROTECTED" },
{ 0x2702, "LOGICAL UNIT SOFTWARE WRITE PROTECTED" },
{ 0x2703, "ASSOCIATED WRITE PROTECT" },
{ 0x2704, "PERSISTENT WRITE PROTECT" },
{ 0x2705, "PERMANENT WRITE PROTECT" },
{ 0x2706, "CONDITIONAL WRITE PROTECT" },
{ 0x2800, "NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED" },
{ 0x2801, "IMPORT OR EXPORT ELEMENT ACCESSED" },
{ 0x2802, "FORMAT-LAYER MAY HAVE CHANGED" },
{ 0x2900, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED" },
{ 0x2901, "POWER ON OCCURRED" },
{ 0x2902, "BUS RESET OCCURRED" },
{ 0x2903, "BUS DEVICE RESET FUNCTION OCCURRED" },
{ 0x2904, "DEVICE INTERNAL RESET" },
{ 0x2A00, "PARAMETERS CHANGED" },
{ 0x2A01, "MODE PARAMETERS CHANGED" },
{ 0x2A02, "LOG PARAMETERS CHANGED" },
{ 0x2A03, "RESERVATIONS PREEMPTED" },
{ 0x2B00, "COPY CANNOT EXECUTE SINCE INITIATOR CANNOT DISCONNECT" },
{ 0x2C00, "COMMAND SEQUENCE ERROR" },
{ 0x2C03, "CURRENT PROGRAM AREA IS NOT EMPTY" },
{ 0x2C04, "CURRENT PROGRAM AREA IS EMPTY" },
{ 0x2E00, "INSUFFICIENT TIME FOR OPERATION" },
{ 0x2F00, "COMMANDS CLEARED BY ANOTHER INITIATOR" },
{ 0x3000, "INCOMPATIBLE MEDIUM INSTALLED" },
{ 0x3001, "CANNOT READ MEDIUM - UNKNOWN FORMAT" },
{ 0x3002, "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT" },
{ 0x3003, "CLEANING CARTRIDGE INSTALLED" },
{ 0x3004, "CANNOT WRITE MEDIUM - UNKNOWN FORMAT" },
{ 0x3005, "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT" },
{ 0x3006, "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM" },
{ 0x3007, "CLEANING FAILURE" },
{ 0x3008, "CANNOT WRITE - APPLICATION CODE MISMATCH" },
{ 0x3009, "CURRENT SESSION NOT FIXATED FOR APPEND" },
{ 0x3010, "MEDIUM NOT FORMATTED" },
{ 0x3011, "CANNOT WRITE MEDIUM - UNSUPPORTED MEDIUM VERSION" },
{ 0x3100, "MEDIUM FORMAT CORRUPTED" },
{ 0x3101, "FORMAT COMMAND FAILED" },
{ 0x3102, "ZONED FORMATTING FAILED DUE TO SPARE LINKING" },
{ 0x3200, "NO DEFECT SPARE LOCATION AVAILABLE" },
{ 0x3400, "ENCLOSURE FAILURE" },
{ 0x3500, "ENCLOSURE SERVICES FAILURE" },
{ 0x3501, "UNSUPPORTED ENCLOSURE FUNCTION" },
{ 0x3502, "ENCLOSURE SERVICES UNAVAILABLE" },
{ 0x3503, "ENCLOSURE SERVICES TRANSFER FAILURE" },
{ 0x3504, "RNCLOSURE SERVICES TRANSFER REFUSED" },
{ 0x3505, "ENCLOSURE SERVICES CHECKSUM ERROR" },
{ 0x3700, "ROUNDED PARAMETER" },
{ 0x3900, "SAVING PARAMETERS NOT SUPPORTED" },
{ 0x3A00, "MEDIUM NOT PRESENT" },
{ 0x3A01, "MEDIUM NOT PRESENT - TRAY CLOSED" },
{ 0x3A02, "MEDIUM NOT PRESENT - TRAY OPEN" },
{ 0x3A03, "MEDIUM NOT PRESENT - LOADABLE" },
{ 0x3B0D, "MEDIUM DESTINATION ELEMENT FULL" },
{ 0x3B0E, "MEDIUM SOURCE ELEMENT EMPTY" },
{ 0x3B0F, "END OF MEDIUM REACHED" },
{ 0x3B11, "MEDIUM MAGAZINE NOT ACCESSIBLE" },
{ 0x3B12, "MEDIUM MAGAZINE REMOVED" },
{ 0x3B13, "MEDIUM MAGAZINE INSERTED" },
{ 0x3B14, "MEDIUM MAGAZINE LOCKED" },
{ 0x3B15, "MEDIUM MAGAZINE UNLOCKED" },
{ 0x3B16, "MECHANICAL POSITIONING OR CHANGER ERROR" },
{ 0x3D00, "INVALID BITS IN IDENTIFY MESSAGE" },
{ 0x3E00, "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET" },
{ 0x3E01, "LOGICAL UNIT FAILURE" },
{ 0x3E02, "TIMEOUT ON LOGICAL UNIT" },
{ 0x3F00, "TARGET OPERATING CONDITIONS HAVE CHANGED" },
{ 0x3F01, "MICROCODE HAS BEEN CHANGED" },
{ 0x3F02, "CHANGED OPERATING DEFINITION" },
{ 0x3F03, "INQUIRY DATA HAS CHANGED" },
{ 0x4300, "MESSAGE ERROR" },
{ 0x4400, "INTERNAL TARGET FAILURE" },
{ 0x4500, "SELECT OR RESELECT FAILURE" },
{ 0x4600, "UNSUCCESSFUL SOFT RESET" },
{ 0x4700, "SCSI PARITY ERROR" },
{ 0x4800, "INITIATOR DETECTED ERROR MESSAGE RECEIVED" },
{ 0x4900, "INVALID MESSAGE ERROR" },
{ 0x4A00, "COMMAND PHASE ERROR" },
{ 0x4B00, "DATA PHASE ERROR" },
{ 0x4C00, "LOGICAL UNIT FAILED SELF-CONFIGURATION" },
{ 0x4E00, "OVERLAPPED COMMANDS ATTEMPTED" },
{ 0x5100, "ERASE FAILURE" },
{ 0x5101, "ERASE FAILURE - INCOMPLETE ERASE OPERATION DETECTED" },
{ 0x5300, "MEDIA LOAD OR EJECT FAILED" },
{ 0x5302, "MEDIUM REMOVAL PREVENTED" },
{ 0x5500, "SYSTEM RESOURCE FAILURE" },
{ 0x5700, "UNABLE TO RECOVER TABLE-OF-CONTENTS" },
{ 0x5A00, "OPERATOR REQUEST OR STATE CHANGE INPUT" },
{ 0x5A01, "OPERATOR MEDIUM REMOVAL REQUEST" },
{ 0x5A02, "OPERATOR SELECTED WRITE PROTECT" },
{ 0x5A03, "OPERATOR SELECTED WRITE PERMIT" },
{ 0x5B00, "LOG EXCEPTION" },
{ 0x5B01, "THRESHOLD CONDITION MET" },
{ 0x5B02, "LOG COUNTER AT MAXIMUM" },
{ 0x5B03, "LOG LIST CODES EXHAUSTED" },
{ 0x5D00, "FAILURE PREDICTION THRESHOLD EXCEEDED" },
{ 0x5D01, "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED" },
{ 0x5D02, "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED" },
{ 0x5D03, "SPARE AREA EXHAUSTION FAILURE PREDICTION THRESHOLD EXCEEDED" },
{ 0x5DFF, "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)" },
{ 0x5E00, "LOW POWER CONDITION ON" },
{ 0x5E01, "IDLE CONDITION ACTIVATED BY TIMER" },
{ 0x5E02, "STANDBY CONDITION ACTIVATED BY TIMER" },
{ 0x5E03, "IDLE CONDITION ACTIVATED BY COMMAND" },
{ 0x5E04, "STANDBY CONDITION ACTIVATED BY COMMAND" },
{ 0x6300, "END OF USER AREA ENCOUNTERED ON THIS TRACK" },
{ 0x6301, "PACKET DOES NOT FIT IN AVAILABLE SPACE" },
{ 0x6400, "ILLEGAL MODE FOR THIS TRACK" },
{ 0x6401, "INVALID PACKET SIZE" },
{ 0x6500, "VOLTAGE FAULT" },
{ 0x6F00, "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE" },
{ 0x6F01, "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT" },
{ 0x6F02, "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED" },
{ 0x6F03, "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION" },
{ 0x6F04, "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION" },
{ 0x6F05, "LOGICAL UNIT REGION MUST BE PERMANENT/REGION RESET COUNT ERROR" },
{ 0x6F06, "INSUFFICIENT BLOCK COUNT FOR BINDING NONCE RECORDING" },
{ 0x6F07, "CONFLICT IN BINDING NONCE RECORDING" },
{ 0x7200, "SESSION FIXATION ERROR" },
{ 0x7201, "SESSION FIXATION ERROR WRITING LEAD-IN" },
{ 0x7202, "SESSION FIXATION ERROR WRITING LEAD-OUT" },
{ 0x7203, "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION" },
{ 0x7204, "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK" },
{ 0x7205, "NO MORE TRACK RESERVATIONS ALLOWED" },
{ 0x7206, "RMZ EXTENSION IS NOT ALLOWED" },
{ 0x7207, "NO MORE TEST ZONE EXTENSIONS ARE ALLOWED" },
{ 0x7300, "CD CONTROL ERROR" },
{ 0x7301, "POWER CALIBRATION AREA ALMOST FULL" },
{ 0x7302, "POWER CALIBRATION AREA IS FULL" },
{ 0x7303, "POWER CALIBRATION AREA ERROR" },
{ 0x7304, "PROGRAM MEMORY AREA UPDATE FAILURE" },
{ 0x7305, "PROGRAM MEMORY AREA IS FULL" },
{ 0x7306, "RMA/PMA IS ALMOST FULL" },
{ 0x7310, "CURRENT POWER CALIBRATION AREA IS ALMOST FULL" },
{ 0x7311, "CURRENT POWER CALIBRATION AREA IS FULL" },
{ 0x7317, "RDZ IS FULL" },
{ 0xFFFF, NULL }
};
int sz = sizeof(_table)/sizeof(_table[0])/2,i=sz;
code &= 0xFFFF;
while (sz)
{ if (_table[i].code == code) return _table[i].msg;
if (_table[i].code > code)
{ if (sz/=2) i -= sz;
else while (_table[--i].code > code);
}
else
{ if (sz/=2) i += sz;
else while (_table[++i].code < code);
}
}
return _table[i].code==code ? _table[i].msg : NULL;
}

326
btcflash.cpp Normal file
View File

@ -0,0 +1,326 @@
/*
* Firmware flash utility for BTC DRW1008 DVD+/-RW recorder
* Version 2004/04/29
* By David Huang <khym@azeotrope.org>
* This work is dedicated to the public domain
*
* This utility may also work with other BTC DVD recorders, such as
* the DRW1004 and DRW1108, but they have not been tested.
*
* USE AT YOUR OWN RISK!
* btcflash is provided AS IS, with NO WARRANTY, either expressed or implied.
*
* Requires "transport.hxx" from Andy Polyakov's DVD+RW tools:
* http://fy.chalmers.se/~appro/linux/DVD+RW/tools/
* If obtained as part of dvd+rw-tools it can be built with
* 'make +btcflash'.
*
* Firmware files may be obtained by running BTC's Windows flash
* utility, then searching in the WINDOWS\TEMP or WINNT\TEMP directory
* for a *.HEX file. It will probably be in a subdirectory named
* PAC*.tmp.DIR, and the HEX file will be named Vnnnn.HEX, where nnnn
* is the firmware version number. You'll also find IDEFLASH.EXE or
* BTCFLASH.EXE in the same directory.
*
* This utility will also accept firmware files in ".BIN" format.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "transport.hxx"
const unsigned int FLASHSIZE = 0x100000; /* BTC flash is 1MB */
unsigned char *loadfirmware(const char *);
int getbyte(char *&);
unsigned short calcsum(unsigned char *);
unsigned char *
loadfirmware(const char *firmware)
{
FILE *f;
char line[80], *p;
unsigned char *fwbuf;
int bank, length, offset, type, hexsum;
int i, b;
fwbuf = new unsigned char[FLASHSIZE];
if (!fwbuf) {
fprintf(stderr, "Could not allocate memory for firmware\n");
return NULL;
}
f = fopen(firmware, "r");
if (!f) {
fprintf(stderr, "%s: Unable to open: ", firmware);
perror(NULL);
return NULL;
}
// Get length of file. If it's exactly FLASHSIZE, assume it's a
// .bin file. Otherwise, try to read it as a .hex file.
fseek(f, 0, SEEK_END);
if (ftell(f) == FLASHSIZE) {
rewind(f);
if (fread(fwbuf, 1, FLASHSIZE, f) != FLASHSIZE) {
fprintf(stderr, "%s: Short read\n", firmware);
return NULL;
}
fclose(f);
return fwbuf;
}
rewind(f);
memset(fwbuf, 0xff, FLASHSIZE);
bank = 0;
while (fgets(line, sizeof(line), f)) {
if (line[0] != ':')
continue;
p = line + 1;
length = getbyte(p);
offset = getbyte(p) << 8 | getbyte(p);
type = getbyte(p);
if (length < 0 || offset < 0 || type < 0 ||
(type != 0 && length != 0)) {
fprintf(stderr, "Malformed line: %s", line);
return NULL;
} else if (length == 0) {
if (strncmp(line, ":00000155AA", 11) == 0) {
if (++bank >= 16) {
fprintf(stderr,
"Firmware file larger than 1MB\n");
return NULL;
}
continue;
} else if (strncmp(line, ":00000001FF", 11) == 0)
break;
else {
fprintf(stderr, "Malformed line: %s", line);
return NULL;
}
}
hexsum = (length + (offset >> 8) + (offset & 0xff)) & 0xff;
for (i = 0; i < length; i++, offset++) {
b = getbyte(p);
hexsum = (hexsum + b) & 0xff;
if (b < 0) {
fprintf(stderr, "Short line: %s", line);
return NULL;
}
fwbuf[(bank << 16) | offset] = (char)b;
}
hexsum = (0x100 - hexsum) & 0xff;
if (hexsum != getbyte(p)) {
fprintf(stderr, "Checksum mismatch: %s", line);
return NULL;
}
}
fclose(f);
if (bank != 15) {
fprintf(stderr, "Firmware file too small\n");
return NULL;
}
return fwbuf;
}
int
getbyte(char *&p)
{
int h, l;
h = *p;
if (h >= '0' && h <= '9')
h -= '0';
else if (h >= 'A' && h <= 'F')
h -= 'A' - 10;
else if (h >= 'a' && h <= 'f')
h -= 'a' - 10;
else
return -1;
l = *(p+1);
if (l >= '0' && l <= '9')
l -= '0';
else if (l >= 'A' && l <= 'F')
l -= 'A' - 10;
else if (l >= 'a' && l <= 'f')
l -= 'a' - 10;
else
return -1;
p += 2;
return (h << 4) | l;
}
unsigned short
calcsum(unsigned char *fwbuf)
{
unsigned int flashsum, i;
for(flashsum = 0, i = 0; i < FLASHSIZE; i++)
flashsum += fwbuf[i];
return (flashsum & 0xffff);
}
int main(int argc, char *argv[])
{
const char *fwfile;
char confirm[5];
unsigned char *fwbuf, inq[128], csbuf[32];
unsigned short checksum;
Scsi_Command cmd;
int err;
unsigned int offset;
if (argc < 3) {
fprintf(stderr, "Usage: %s /dev/cdrom firmware\n",
argv[0]);
return 1;
}
printf("BTC DVD+/-RW firmware flash utility 2004/04/29\n");
printf("USE AT YOUR OWN RISK!\n\n");
if (!cmd.associate(argv[1])) {
fprintf(stderr, "%s: unable to open: ", argv[1]);
perror (NULL);
return 1;
}
fwfile = argv[2];
if (!(fwbuf = loadfirmware(fwfile)))
return 1;
checksum = calcsum(fwbuf);
printf("Loaded firmware from %s\nFirmware checksum is %04X\n",
fwfile, checksum);
cmd[0] = 0x12; // INQUIRY
cmd[4] = 36;
cmd[5] = 0;
if (err = cmd.transport(READ, inq, 36)) {
sperror("INQUIRY", err);
return 1;
}
printf("Drive is currently: [%.8s][%.16s][%.4s]\n",
inq+8, inq+16, inq+32);
printf("Firmware appears to be: [%.8s][%.16s][%.4s]\n\n",
fwbuf+0x40bc, fwbuf+0x40c4, fwbuf+0x40d4);
if (strncmp((char*)inq + 8, (char*)fwbuf + 0x40bc, 24) != 0)
printf(
"***********************************************"
"***********\n"
"WARNING! THIS FIRMWARE DOES NOT SEEM TO BE FOR "
"THIS DRIVE!\n"
"***********************************************"
"***********\n");
printf("Type \"YES\" to proceed with flash: ");
fflush(stdout);
fgets(confirm, sizeof(confirm), stdin);
if (strcmp(confirm, "YES\n") != 0) {
printf("\nFlash canceled.\n");
return 0;
}
printf("\nUploading firmware...\n");
// Upload firmware
for (offset = 0; offset < FLASHSIZE; offset += 0x1000) {
cmd[0] = 0x3B; // WRITE BUFFER
cmd[1] = 6; // Download Microcode with Offsets
cmd[2] = 0; // Buffer ID 0
cmd[3] = (offset >> 16) & 0xff;
cmd[4] = (offset >> 8) & 0xff;
cmd[5] = 0x20;
cmd[6] = 0; // Length 0x1000
cmd[7] = 0x10;
cmd[8] = 0;
cmd[9] = 0;
if (err = cmd.transport(WRITE, fwbuf + offset, 0x1000)) {
sperror("WRITE BUFFER[1]", err);
return 1;
}
}
// Upload checksum
memset(csbuf, 0, 32);
csbuf[30] = (checksum >> 8);
csbuf[31] = (checksum & 0xff);
cmd[0] = 0x3B; // WRITE BUFFER
cmd[1] = 6; // Download Microcode with Offsets
cmd[2] = 0; // Buffer ID 0
cmd[3] = 0; // Offset 0
cmd[4] = 0;
cmd[5] = 0;
cmd[6] = 0; // Length 0x20
cmd[7] = 0;
cmd[8] = 0x20;
cmd[9] = 0;
if (err = cmd.transport(WRITE, csbuf, 0x20)) {
sperror("WRITE BUFFER[2]", err);
return 1;
}
printf("Flashing drive...\n");
// Firmware uploaded; now flash it!
cmd[0] = 0x3B; // WRITE BUFFER
cmd[1] = 7; // Download Microcode with Offsets and Save
cmd[2] = 0; // Buffer ID 0
cmd[3] = 0; // Offset 0
cmd[4] = 0;
cmd[5] = 0;
cmd[6] = 0; // Length 0
cmd[7] = 0;
cmd[8] = 0;
cmd[9] = 0;
if (err = cmd.transport()) {
sperror("WRITE BUFFER[3]", err);
return 1;
}
sleep(50); // Let drive sit for a while before bothering it
while (1) {
sleep(1);
cmd[0] = 0; // TEST UNIT READY
cmd[5] = 0;
err = cmd.transport();
// Wait until it returns either ready or
// not ready/medium not present
if ((err == 0) || (SK(err) == 2 && ASC(err) == 0x3A))
break;
}
cmd[0] = 0x12; // INQUIRY
cmd[4] = 36;
cmd[5] = 0;
if (err = cmd.transport(READ, inq, 36)) {
sperror("INQUIRY[2]", err);
return 1;
}
printf("Drive is now: [%.8s][%.16s][%.4s]\n\n",
inq+8, inq+16, inq+32);
printf("Please reboot before using the drive.\n");
return 0;
}

831
dvd+rw-booktype.cpp Normal file
View File

@ -0,0 +1,831 @@
#if 0
#
# Utility for manipulating Book Type Field of Physical Format Descriptor
# located in lead-in of DVD+RW media. This is 9th version. 2nd version
# added initial support for 2nd generation DVD+RW drives. 3rd version
# adds support for DVD+R unit settings. 4th version checks if the unit
# is of RICOH design and reliably recognizes drive generation. 5th
# version adds support for Benq derivatives. 6th version fixes problem
# with USB connected units? 7th version adds support for BTC units.
# 8th version fixes typos in BTC support, adds support for fraudulent
# NEC firmwares and Lite-On based units. 9th version adds support for
# LG, Plextor and dual-format and double-layer Benq units. Keep in mind
# that booktyping support might appear in certain firmware revisions,
# not necessarily all.
#
# The code is in public domain.
#
# See http://www.dvdplusrw.org/resources/bitsettings.html
# for further details.
#
/bin/sh << EOS
MODNAME=\`expr "/$0" : '\(.*[^/]\)/*$' : '.*/\(..*\)' : '\(.*\)\..*$'\`
case "`uname -s`" in
SunOS) (set -x; g++ -fno-exceptions -O -o \$MODNAME "$0" -lvolmgt) ;;
*) (set -x; g++ -fno-exceptions -O -o \$MODNAME "$0") ;;
esac
EOS
exit
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "transport.hxx"
#define OPT_MEDIA 0x01
#define OPT_UNIT 0x02
#define OPT_UNITRW 0x03
#define OPT_UNITR 0x04
#define OPT_MASK 0x0F
#define OPT_INQ 0x10
#define INTERNAL_RELOAD 0x20
unsigned short profile;
const char *dev;
const char *bookname (unsigned char book,char *unknown=NULL)
{ const char *ret;
switch(book&0xF0)
{ case 0x00: ret="-ROM"; break;
case 0x10: ret="-RAM"; break;
case 0x20: ret="-R"; break;
case 0x30: ret="-RW"; break;
case 0x90: ret="+RW"; break;
case 0xA0: ret="+R"; break;
case 0xE0: ret="+R DL"; break;
default: ret=NULL;
if (unknown) sprintf (unknown,"?%02X",book&0xFF);
break;
}
return ret;
}
int mediainfo (Scsi_Command &cmd)
{ unsigned char buf[8],book;
const char *brand;
int err;
cmd[0]=0xAD; // READ DVD STRUCTURE
cmd[9]=sizeof(buf);
cmd[11]=0;
if ((err=cmd.transport(READ,buf,sizeof(buf))))
{ sperror ("READ DVD STRUCTURE#0",err);
return 1;
}
book=buf[4];
brand=bookname (book);
printf ("Current media Book Type Field is %02xh: ",book);
if (brand) printf ("DVD%s specification [revision %d]\n",
brand,book&0xF);
else printf ("unrecognized value\n");
return 0;
}
int ricoh (Scsi_Command &cmd,int action,int book,int gen=2)
{ int err,cnt=0;
unsigned char buf[6];
const char *brand;
char unknown [16]="?unknown";
switch (action)
{ case OPT_INQ|OPT_MEDIA:
break;
case OPT_INQ:
case OPT_INQ|OPT_UNIT:
if (gen==1) goto inq_unitrw;
cmd[0]=0xFA;
cmd[1]=0x10;
cmd[8]=sizeof(buf);
cmd[11]=0;
if (!cmd.transport(READ,buf,sizeof(buf)))
{ brand = bookname (buf[4],unknown),
printf ("The unit will brand DVD+R media as DVD%s\n",
brand?brand:unknown),
cnt++;
}
case OPT_INQ|OPT_UNITRW:
inq_unitrw:
cmd[0]=0xFA;
cmd[1]=0x00;
cmd[8]=sizeof(buf);
cmd[11]=0;
if (!cmd.transport(READ,buf,sizeof(buf)))
{ brand = bookname (buf[4],unknown),
printf ("The unit will format DVD+RW media as DVD%s\n",
brand?brand:unknown),
cnt++;
}
if (cnt==0)
printf ("Unable to determine unit settings. "
"Default settings vary from\n"
"firmware to firmware. Set "
"explicitly to be certain.\n");
break;
case OPT_INQ|OPT_UNITR:
if (gen==1)
{ fprintf (stderr,":-( not applicable to 1st gen unit\n");
return 1;
}
cmd[0]=0xFA;
cmd[1]=0x10;
cmd[8]=sizeof(buf);
cmd[11]=0;
if (!cmd.transport(READ,buf,sizeof(buf)))
{ brand = bookname (buf[4],unknown),
printf ("The unit will brand DVD+R media as DVD%s\n",
brand?brand:unknown);
}
break;
case OPT_MEDIA:
if (profile!=0x1A)
{ fprintf (stderr,":-( action is applicable to DVD+RW only\n");
break;
}
if (book != 0x92 && book != 0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
cmd[0]=0xF9;
cmd[1]=0x02;
cmd[2]=book;
cmd[3]=(gen==1?0:0xFF);
cmd[11]=0;
if ((err=cmd.transport()))
return sperror("RICOH_F9h(2)",err),1;
else
return mediainfo(cmd);
break;
case OPT_UNIT:
if (profile==0x1B || profile==0x2B) goto set_unitr;
case OPT_UNITRW:
if (book != 0x92 && book != 0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
cmd[0]=0xF9;
cmd[1]=(gen==1?0x01:0x0C);
cmd[2]=book;
cmd[3]=(gen==1?0:0xFF);
cmd[11]=0;
if ((err=cmd.transport()))
sperror (gen==1?"RICOH(1)":"RICOH(0Ch)",err);
else
printf ("Unit was instructed to format DVD+RW as DVD%s\n",
book==0x01?"-ROM":"+RW");
break;
case OPT_UNITR:
set_unitr:
if (gen==1)
{ fprintf (stderr,":-( not applicable to 1st gen unit\n");
return 1;
}
if (book != 0xA1 && book != 0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
cmd[0]=0xF9;
cmd[1]=0x14;
cmd[2]=book;
cmd[3]=0xFF;
cmd[11]=0;
if ((err=cmd.transport()))
sperror ("RICOH(14h)",err);
else
printf ("Unit was instructed to brand DVD+R as DVD%s\n",
book==0x01?"-ROM":"+R");
break;
default:
break;
}
return 0;
}
int benq (Scsi_Command &cmd,int action,int book,int gen=2)
{ int err;
unsigned char word[2];
const char *brand;
char unknown [16]="?unknown";
switch (action)
{ case OPT_INQ|OPT_MEDIA:
break;
case OPT_INQ:
case OPT_INQ|OPT_UNIT:
cmd[0]=0xFF;
cmd[1]=0x10;
cmd[11]=0;
if ((err=cmd.transport(READ,word,sizeof(word))))
sperror ("BENQ_FFh(10h)",err);
else
{ brand = bookname (word[0],unknown),
printf ("The unit will brand DVD+R media as DVD%s\n",
brand?brand:unknown);
}
case OPT_INQ|OPT_UNITRW:
cmd[0]=0xFF;
cmd[1]=0x00;
cmd[11]=0;
if ((err=cmd.transport(READ,word,sizeof(word))))
sperror ("BENQ_FFh(00h)",err);
else
{ brand = bookname (word[0],unknown),
printf ("The unit will format DVD+RW media as DVD%s\n",
brand?brand:unknown);
}
break;
case OPT_INQ|OPT_UNITR:
cmd[0]=0xFF;
cmd[1]=0x10;
cmd[11]=0;
if ((err=cmd.transport(READ,word,sizeof(word))))
sperror ("BENQ_FFh(10h)",err);
else
{ brand = bookname (word[0],unknown),
printf ("The unit will brand DVD+R media as DVD%s\n",
brand?brand:unknown);
}
if (gen<3) break;
cmd[0]=0xFF;
cmd[1]=0x10;
cmd[2]=0x01;
cmd[11]=0;
if ((err=cmd.transport(READ,word,sizeof(word))))
sperror ("BENQ_FFh(10h,1)",err);
else
{ brand = bookname (word[0],unknown),
printf ("The unit will brand DVD+R DL meda as DVD%s\n",
brand?brand:unknown);
}
break;
case OPT_MEDIA:
if (profile!=0x1A)
{ fprintf (stderr,":-( action is applicable to DVD+RW only\n");
break;
}
if (book != 0x92 && book != 0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
#if 0
cmd[0]=0x1E; // PREVENT/ALLOW MEDIA REMOVAL
cmd[4]=1; // "Prevent"
cmd[5]=0;
if ((err=cmd.transport()))
{ sperror ("PREVENT MEDIA REMOVAL",err);
break;
}
#endif
cmd[0]=0xFE;
cmd[1]=2;
cmd[2]=book;
cmd[11]=0;
if ((err=cmd.transport()))
sperror ("BENQ_FEh(2)",err);
else
action = INTERNAL_RELOAD;
break;
case OPT_UNIT:
if (profile==0x1B || profile==0x2B) goto set_unitr;
case OPT_UNITRW:
if (book != 0x92 && book != 0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
cmd[0]=0xFE;
cmd[1]=4;
cmd[2]=book;
cmd[11]=0;
if ((err=cmd.transport()))
sperror ("BENQ_FEh(4)",err);
else
printf ("Unit was instructed to format DVD+RW as DVD%s\n",
book==0x01?"-ROM":"+RW");
break;
case OPT_UNITR:
set_unitr:
if (book != 0xA1 && book != 0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
cmd[0]=0xFE;
cmd[1]=5;
cmd[2]=book;
cmd[11]=0;
if ((err=cmd.transport()))
sperror ("BENQ_FEh(5)",err);
else
printf ("Unit was instructed to brand DVD+R as DVD%s\n",
book==0x01?"-ROM":"+R");
if (gen<3) break;
cmd[0]=0xFE;
cmd[0]=5;
cmd[2]=book==0x01?0x01:0xE1;
cmd[3]=1;
cmd[11]=0;
if ((err=cmd.transport()))
sperror ("BENQ_FEh(5,1)",err);
else
printf ("Unit was instructed to brand DVD+R DL as DVD%s\n",
book==0x01?"-ROM":"+R DL");
break;
default:
break;
}
cmd[0]=0xFD;
cmd[1]=0xF2;
cmd[2]='B';
cmd[3]='E';
cmd[4]='N';
cmd[5]='Q';
cmd[11]=0;
if ((err=cmd.transport()))
sperror ("BENQ_FDh(F2h)",err);
if (action!=INTERNAL_RELOAD)
return 0;
cmd[0]=0x1E; // PREVENT/ALLOW MEDIA REMOVAL
cmd[5]=0;
if ((err=cmd.transport()))
return sperror ("ALLOW MEDIA REMOVAL",err),1;
cmd[0]=0x1B; // START/STOP UNIT
cmd[4]=0x2; // "Eject"
cmd[5]=0;
if ((err=cmd.transport()))
return sperror ("EJECT",err),1;
cmd[0]=0x1B; // START/STOP UNIT
cmd[4]=0x3; // "Load"
cmd[5]=0;
if ((err=cmd.transport()))
return sperror ("LOAD TRAY",err),1;
if (wait_for_unit (cmd)) return 1;
return mediainfo (cmd);
}
int btc (Scsi_Command &cmd,int action,int book,int gen=0)
{ int err,obligatory=0;
const char *brand="";
switch (action)
{ case OPT_INQ|OPT_MEDIA:
break;
case OPT_INQ:
case OPT_INQ|OPT_UNIT:
case OPT_INQ|OPT_UNITRW:
case OPT_INQ|OPT_UNITR:
fprintf (stderr,":-( Can't inquiry unit settings, "
"you have to set booktype prior every "
"recording to be sure.\n");
return 1;
break;
case OPT_MEDIA:
if (profile!=0x1A && profile!=0x14 && profile!=13)
{ fprintf (stderr,":-( action is applicable to DVD±RW only\n");
break;
}
obligatory = (profile==0x1A)?0x92:0x32;
if (book!=obligatory && book!=0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
break;
}
cmd[0]=0x1E; // PREVENT/ALLOW MEDIA REMOVAL
cmd[4]=1; // "Prevent"
cmd[5]=0;
if ((err=cmd.transport()))
{ sperror ("PREVENT MEDIA REMOVAL",err);
break;
}
cmd[0]=0xFA;
cmd[2]=book;
cmd[10]=0xAA;
cmd[11]=0xFF;
if ((err=cmd.transport()))
sperror ("BTC_FAh[2]",err);
else
wait_for_unit (cmd);
cmd[0]=0x1E; // PREVENT/ALLOW MEDIA REMOVAL
cmd[5]=0;
if ((err=cmd.transport()))
return sperror ("ALLOW MEDIA REMOVAL",err),1;
break;
case OPT_UNIT:
if (profile==0x1B || profile==0x2B || profile==0x11)
goto set_unitr;
case OPT_UNITRW:
fprintf (stderr,":-( Can't set RW unit settings, "
"manipulate media.\n");
return 1;
break;
case OPT_UNITR:
set_unitr:
// unit requires media in, so we can rely on profile...
if (profile==0x1B) obligatory=0xA1, brand="+R";
else if (profile==0x2B) obligatory=0xE1, brand="+R DL";
else obligatory=0x20, brand="-R";
if (book!=obligatory && book!=0x01)
{ fprintf (stderr,":-( BookType#%02x is not applicable\n",book);
return 1;
}
cmd[0]=0xFA;
cmd[3]=book;
cmd[4]=book==0x01?0:1;
cmd[10]=0xAA;
cmd[11]=0xFF;
if ((err=cmd.transport()))
return sperror ("BTC_FAh[3]",err),1;
else
printf ("Unit was instructed to brand DVD%s as DVD%s\n",
brand,book==0x01?"-ROM":brand);
return 0;
break;
default:
break;
}
return mediainfo (cmd);
}
int liteon (Scsi_Command &cmd,int action,int book,unsigned char *buf=NULL)
{ int err;
switch (action)
{ case OPT_INQ|OPT_MEDIA:
break;
case OPT_INQ:
case OPT_INQ|OPT_UNIT:
case OPT_INQ|OPT_UNITRW:
case OPT_INQ|OPT_UNITR:
if (buf==NULL || buf[0]==0)
{ printf ("Unit will brand DVD+plus media with "
"corresponding booktype, e.g. DVD+R as DVD+R...\n");
return buf==NULL?1:0;
}
if (buf[0]==1)
printf ("Unit will brand DVD+plus media as DVD-ROM\n");
else if (buf[0]==2)
printf ("Unit will format DVD+RW media as DVD+RW\n");
else
fprintf (stderr,":-? Insane unit setting %02x\n",buf[0]);
return buf[0]==1?0:1;
break;
case OPT_MEDIA:
fprintf (stderr,":-( Direct DVD+RW media manipulations "
"are not supported.\n"
" Use -unit flag instead and apply "
"-dvd-compat recordinging procedure.\n");
return 1;
break;
case OPT_UNIT:
case OPT_UNITRW:
case OPT_UNITR:
cmd[0]=0xDF;
cmd[2]=0x0F;
cmd[3]=1;
cmd[4]=book==0x01?1:0;
cmd[11]=0;
if ((err=cmd.transport()))
return sperror ("LITEON_DFh[1]",err),1;
if (book==0x01)
printf ("Unit was instructed to brand DVD+plus media "
"as DVD-ROM\n");
else
printf ("Unit was instructed to brand DVD+plus media with "
"corresponding booktype, e.g. DVD+R as DVD+R...\n");
return 0;
break;
default:
break;
}
return mediainfo (cmd);
}
// As per http://www-user.tu-chemnitz.de/~noe/Bitsetting/
int plextor (Scsi_Command &cmd,int action,int book,int gen=2)
{ int err;
unsigned char vector[8];
switch (action)
{ case OPT_INQ|OPT_MEDIA:
break;
case OPT_INQ|OPT_UNITRW:
case OPT_UNITRW:
case OPT_MEDIA:
fprintf (stderr,":-( DVD+RW booktyping is not supported\n");
return 1;
break;
case OPT_INQ:
case OPT_INQ|OPT_UNIT:
case OPT_INQ|OPT_UNITR:
cmd[0] = 0xE9;
cmd[2] = 0x22;
cmd[3] = 0x0A;
cmd[9] = sizeof(vector);
cmd[11] = 0;
if ((err=cmd.transport(READ,vector,sizeof(vector))))
return sperror ("PLEXTOR_E9h(A)",err),1;
printf ("Unit will brand DVD+R media as DVD%s\n",
vector[2]?"-ROM":"+R");
if (gen<3) return 0;
cmd[0] = 0xE9;
cmd[2] = 0x22;
cmd[3] = 0x0E;
cmd[9] = sizeof(vector);
cmd[11] = 0;
if ((err=cmd.transport(READ,vector,sizeof(vector))))
return sperror ("PLEXTOR_E9h(E)",err),1;
printf ("Unit will brand DVD+R DL media as DVD%s\n",
vector[2]?"-ROM":"+R DL");
return 0;
break;
case OPT_UNIT:
case OPT_UNITR:
cmd[0] = 0xE9;
cmd[1] = 0x10;
cmd[2] = 0x22;
cmd[3] = 0x0A;
cmd[5] = book&0xF0?0:1;
cmd[9] = sizeof(vector);
cmd[11] = 0;
if ((err=cmd.transport(READ,vector,sizeof(vector))))
return sperror ("PLEXTOR_E9h(A)",err),1;
printf ("Unit was instructed to brand DVD+R media as DVD%s\n",
book&0xF0?"+R":"-ROM");
if (gen<3) return 0;
cmd[0] = 0xE9;
cmd[1] = 0x10;
cmd[2] = 0x22;
cmd[3] = 0x0E;
cmd[5] = book&0xF0?0:1;
cmd[9] = sizeof(vector);
cmd[11] = 0;
if ((err=cmd.transport(READ,vector,sizeof(vector))))
return sperror ("PLEXTOR_E9h(E)",err),1;
printf ("Unit was instructed to brand DVD+R DL media as DVD%s\n",
book&0xF0?"+R DL":"-ROM");
return 0;
break;
default:
break;
}
return mediainfo (cmd);
}
int lg (Scsi_Command &cmd,int action,int book)
{ int err;
unsigned char vector[4];
switch (action)
{ case OPT_INQ|OPT_MEDIA:
break;
case OPT_INQ|OPT_UNITRW:
case OPT_UNITRW:
case OPT_MEDIA:
fprintf (stderr,":-( DVD+RW booktyping is not supported\n");
return 1;
break;
case OPT_INQ:
case OPT_INQ|OPT_UNIT:
case OPT_INQ|OPT_UNITR:
cmd[0] = 0xFA;
cmd[8] = sizeof(vector);
cmd[9] = 0;
if ((err=cmd.transport(READ,vector,sizeof(vector))))
return sperror ("LG_FAh",err),1;
printf ("Unit will brand DVD+R media as DVD%s\n",
vector[0]&0xF0?"+R":"-ROM");
printf ("Unit will brand DVD+R DL media as DVD%s\n",
vector[1]&0xF0?"+R DL":"-ROM");
return 0;
break;
case OPT_UNIT:
case OPT_UNITR:
memset (vector,0,sizeof(vector));
if (book&0xF0)
vector[0] = 0xA0, // DVD+R
vector[1] = 0xE0; // DVD+R DL
cmd[0] = 0xFC;
cmd[2] = '+';
cmd[3] = 'R';
cmd[4] = 'T';
cmd[5] = 'B';
cmd[8] = sizeof(vector);
cmd[9] = 0;
if ((err=cmd.transport(WRITE,vector,sizeof(vector))))
return sperror ("LG_FCh",err),1;
printf ("Unit was instructed to brand DVD+R media as DVD%s\n",
book&0xF0?"+R":"-ROM");
return 0;
break;
default:
break;
}
return mediainfo (cmd);
}
int main(int argc,char *argv[])
{ Scsi_Command cmd;
unsigned char buf[128];
int book=0,action=0;
int plusgeneration=0,dashcapable=0,ramcapable=0;
int i,err,hp=0,plx=0;
for(dev=NULL,i=1;i<argc;i++)
{ if (!strncmp (argv[i],"-dvd-rom",7)) book=0x01;
else if (!strncmp (argv[i],"-dvd+rw",7)) book=0x92;
else if (!strncmp (argv[i],"-dvd+r",6)) book=0xA1;
else if (!strncmp (argv[i],"-dvd-rw",7)) book=0x32;
else if (!strncmp (argv[i],"-dvd-r",6)) book=0x20;
else if (!strncmp (argv[i],"-inq",4)) book=0xFF, action|=OPT_INQ;
else if (!strncmp (argv[i],"-unit+rw",8)) action&=~OPT_MASK, action|=OPT_UNITRW;
else if (!strncmp (argv[i],"-unit+r",7)) action&=~OPT_MASK, action|=OPT_UNITR;
else if (!strncmp (argv[i],"-unit",3)) action&=~OPT_MASK, action|=OPT_UNIT;
else if (!strncmp (argv[i],"-media",3)) action&=~OPT_MASK, action|=OPT_MEDIA;
else dev=argv[i];
}
if (!(dev && book && action))
{ fprintf (stderr,"Usage: %s "
"[-dvd-rom-spec|-dvd+rw-spec|-dvd+r-spec|-inq] \\\n"
" [-media|-unit|-unit+rw|-unit+r] "
#if defined(_WIN32)
"d:\n",argv[0]),
fprintf (stderr,"For further information see http://"
"www.dvdplusrw.org/resources/bitsettings.html\n");
#else
"/dev/dvd\n",argv[0]);
#endif
return 1;
}
if (!cmd.associate(dev))
{ fprintf (stderr,"%s: unable to open: ",dev), perror (NULL);
return 1;
}
cmd[0] = 0x12; // INQUIRY
cmd[4] = 36;
cmd[5] = 0;
if ((err=cmd.transport(READ,buf,36)))
{ sperror ("INQUIRY",err);
return 1;
}
if ((buf[0]&0x1F) != 5)
{ fprintf (stderr,":-( not an MMC unit!\n");
return 1;
}
hp = !memcmp (buf+8,"HP ",8);
hp = hp || !memcmp (buf+8,"_NEC ",8);
plx = !memcmp (buf+8,"PLEXTOR ",8);
cmd[0]=0x46; // GET CONFIGURATION
cmd[1]=2;
cmd[8]=8;
cmd[9]=0;
if ((err=cmd.transport(READ,buf,8)))
{ sperror ("GET CONFIGURATION",err);
return 1;
}
// See if it's 2 gen drive by checking if DVD+R profile is an option.
// Catch dual- and triple-format units as well...
{ int len=4+(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3]);
if (len>264)
{ fprintf (stderr,":-( insane profile list length [%d]\n",len);
return 1;
}
unsigned char *list=new unsigned char[len];
cmd[0]=0x46; // GET CONFIGURATION
cmd[1]=2;
cmd[7]=len>>8;
cmd[8]=len;
cmd[9]=0;
if ((err=cmd.transport(READ,list,len)))
return sperror("GET CONFIGURATION",err),1;
for (plusgeneration=1,i=12;i<list[11];i+=4)
{ switch (list[i]<<8|list[i+1])
{ case 0x1B: // DVD+R supported
plusgeneration=2; break;
case 0x2B: // DVD+R DL supported
plusgeneration=3; break;
case 0x11: // DVD-R supported
dashcapable=1; break;
case 0x12: // DVD-RAM supported
ramcapable=1; break;
}
}
delete list;
}
profile=buf[6]<<8|buf[7];
if (action==(OPT_INQ|OPT_MEDIA))
{ int ret=1;
if (profile&0x10 || profile==0x2B) ret=mediainfo (cmd);
else if (profile==0) fprintf (stderr,":-( no media mounted\n");
else fprintf (stderr,":-( non-DVD media\n");
return ret;
}
if (!dashcapable || hp)
{ // See if it's a RICOH design...
cmd[0]=0x5A; // MODE SENSE
cmd[1]=0x08; // "Disable Block Descriptors"
cmd[2]=0x30; // RICOH specific page
cmd[8]=12;
cmd[9]=0;
if (!(err=cmd.transport(READ,buf,12)) && buf[8] == 0x30)
return ricoh (cmd,action,book,plusgeneration);
goto benq;
}
else if (plx) // Plextor doesn't seem to re-badge their units...
return plextor (cmd,action,book,plusgeneration);
else if (ramcapable) // LG is the only one we know...
return lg (cmd,action,book);
else
{ // See if it's BTC design...
cmd[0]=0xFA;
cmd[4]=1;
cmd[10]=0xAA;
cmd[11]=0xFF;
if (!(err=cmd.transport()) || ASC(err)==0x24)
return btc (cmd,action,book);
else if (ASC(err)==0x3A)
return fprintf (stderr,":-( BTC_FAh: no media mounted\n"),1;
// See if it's LITE-ON design...
unsigned char buf[0x80];
cmd[0]=0xDF;
cmd[2]=0x0F;
cmd[7]=sizeof(buf);
cmd[11]=0;
if (!(err=cmd.transport(READ,buf,sizeof(buf))))
return liteon (cmd,action,book,buf);
benq:
// See if it's BENQ design...
cmd[0]=0xFD;
cmd[1]=0xF1;
cmd[2]='B';
cmd[3]='E';
cmd[4]='N';
cmd[5]='Q';
cmd[11]=0;
if (!(err=cmd.transport()))
return benq (cmd,action,book,plusgeneration);
}
fprintf (stderr,"This program targets units of "
"RICOH, BENQ, BTC, LITE-ON, LG and PLEXTOR designs.\n"
"%s doesn't appear to be one. Exiting.\n",
dev);
return 1;
}

879
dvd+rw-format.cpp Normal file
View File

@ -0,0 +1,879 @@
/*
* BD/DVD±RW/-RAM format 7.1 by Andy Polyakov <appro@fy.chalmers.se>.
*
* Use-it-on-your-own-risk, GPL bless...
*
* For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/.
*
* Revision history:
*
* 2.0:
* - deploy "IMMED" bit in "FORMAT UNIT";
* 2.1:
* - LP64 fix;
* - USB workaround;
* 3.0:
* - C++-fication for better portability;
* - SYSV signals for better portability;
* - -lead-out option for improved DVD+RW compatibility;
* - tested with SONY DRU-500A;
* 4.0:
* - support for DVD-RW formatting and blanking, tool name becomes
* overloaded...
* 4.1:
* - re-make it work under Linux 2.2 kernel;
* 4.2:
* - attempt to make DVD-RW Quick Format truly quick, upon release
* is verified to work with Pioneer DVR-x05;
* - media reload is moved to growisofs where is actually belongs;
* 4.3:
* - -blank to imply -force;
* - reject -blank in DVD+RW context and -lead-out in DVD-RW;
* 4.4:
* - support for -force=full in DVD-RW context;
* - ask unit to perform OPC if READ DISC INFORMATION doesn't return
* any OPC descriptors;
* 4.5:
* - increase timeout for OPC, NEC multi-format derivatives might
* require more time to fulfill the OPC procedure;
* 4.6:
* - -force to ignore error from READ DISC INFORMATION;
* - -force was failing under FreeBSD with 'unable to unmount';
* - undocumented -gui flag to ease progress indicator parsing for
* GUI front-ends;
* 4.7:
* - when formatting DVD+RW, Pioneer DVR-x06 remained unaccessible for
* over 2 minutes after dvd+rw-format exited and user was frustrated
* to poll the unit himself, now dvd+rw-format does it for user;
* 4.8:
* - DVD-RW format fails if preceeded by dummy recording;
* - make sure we talk to MMC unit, be less intrusive;
* - unify error reporting;
* - permit for -lead-out even for blank DVD+RW, needed(?) for SANYO
* derivatives;
* 4.9:
* - permit for DVD-RW blank even if format descriptors are not present;
* 4.10:
* - add support for DVD-RAM;
* 6.0:
* - versioning harmonization;
* - WIN32 port;
* - Initial DVD+RW Double Layer support;
* - Ignore "WRITE PROTECTED" error in OPC;
* 6.1:
* - ± localization;
* - Treat only x73xx OPC errors as fatal;
* 7.0:
* - Blu-ray Disc support;
* - Mac OS X 10>=2 support;
* 7.1:
* - refine x73xx error treatment;
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__unix) || defined(__unix__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/wait.h>
#endif
#include "transport.hxx"
static void usage (char *prog)
{ fprintf (stderr,"- usage: %s [-force[=full]] [-lead-out|-blank[=full]]\n"
" [-ssa[=none|default|max|XXXm]] /dev/dvd\n",prog),
exit(1);
}
#ifdef _WIN32
#include <process.h>
# if defined(__GNUC__)
# define __shared__ __attribute__((section(".shared"),shared))
# elif defined(_MSC_VER)
# define __shared__
# pragma data_seg(".shared")
# pragma comment(linker,"/section:.shared,rws")
# endif
static volatile int shared_progress_indicator __shared__ = 0;
# if defined(_MSC_VER)
# pragma data_seg()
# endif
static volatile int *progress = &shared_progress_indicator;
static HANDLE Process = NULL;
BOOL WINAPI GoBackground (DWORD code)
{ if (*progress)
{ FreeConsole(); /* detach from console upon ctrl-c or window close */
return TRUE;
}
return FALSE;
}
void KillForeground (void)
{ fprintf(stderr,"\n");
TerminateProcess(Process,0);
}
#else
static volatile int *progress;
#endif
static const char *gui_action=NULL;
static const char *str = "|/-\\",*backspaces="\b\b\b\b\b\b\b\b\b\b";
#if defined(__unix) || defined(__unix__)
extern "C" void alarm_handler (int no)
{ static int i=0,len=1,old_progress=0;
int new_progress = *progress;
if (gui_action)
{ fprintf (stderr,"* %s %.1f%%\n",gui_action,
100.0*new_progress/65536.0);
alarm(3);
return;
}
if (new_progress != old_progress)
len = fprintf (stderr,"%.*s%.1f%%",len,backspaces,
100.0*new_progress/65536.0) - len,
old_progress = new_progress;
else
fprintf (stderr,"\b%c",str[i]),
i++, i&=3;
alarm(1);
}
#endif
int main (int argc, char *argv[])
{ unsigned char formats[260],dinfo[32],inq[128];
char *dev=NULL,*p;
unsigned int capacity,lead_out,mmc_profile,err;
int len,i;
int force=0,full=0,compat=0,blank=0,ssa=0,do_opc=0,gui=0,
blu_ray=0,not_pow=0;
#ifdef _WIN32
DWORD ppid;
char filename[MAX_PATH],*progname;
/*
* Foreground process spawns itself and simply waits for shared
* progress indicator to increment...
*/
if (sscanf(argv[0],":%u:",&ppid) != 1)
{ int i=0,len=1,old_progress=0,new_progress;
sprintf (filename,":%u:",GetCurrentProcessId());
progname = argv[0];
argv[0] = filename;
Process = (HANDLE)_spawnv (_P_NOWAIT,progname,argv);
if (Process == (HANDLE)-1)
perror("_spawnv"), ExitProcess(errno);
while(1)
{ if (WaitForSingleObject(Process,1000) == WAIT_OBJECT_0)
{ ppid = 0; /* borrow DWORD variable */
GetExitCodeProcess(Process,&ppid);
ExitProcess(ppid);
}
new_progress = *progress;
if (new_progress != old_progress)
len = fprintf (stderr,"%.*s%.1f%%",len,backspaces,
100.0*new_progress/65536.0) - len,
old_progress = new_progress;
else if (new_progress)
fprintf (stderr,"\b%c",str[i]),
i++, i&=3;
}
}
/*
* ... while background process does *all* the job...
*/
Process = OpenProcess (PROCESS_TERMINATE,FALSE,ppid);
if (Process == NULL)
perror("OpenProcess"), ExitProcess(errno);
atexit (KillForeground);
SetConsoleCtrlHandler (GoBackground,TRUE);
GetModuleFileName (NULL,filename,sizeof(filename));
progname = strrchr(filename,'\\');
if (progname) argv[0] = progname+1;
else argv[0] = filename;
#elif defined(__unix) || defined(__unix__)
pid_t pid;
{ int fd;
char *s;
if ((fd=mkstemp (s=strdup("/tmp/dvd+rw-format.XXXXXX"))) < 0)
fprintf (stderr,":-( unable to mkstemp(\"%s\")",s),
exit(1);
ftruncate(fd,sizeof(*progress));
unlink(s);
progress = (int *)mmap(NULL,sizeof(*progress),PROT_READ|PROT_WRITE,
MAP_SHARED,fd,0);
close (fd);
if (progress == MAP_FAILED)
perror (":-( unable to mmap anonymously"),
exit(1);
}
*progress = 0;
if ((pid=fork()) == (pid_t)-1)
perror (":-( unable to fork()"),
exit(1);
if (pid)
{ struct sigaction sa;
sigaction (SIGALRM,NULL,&sa);
sa.sa_flags &= ~SA_RESETHAND;
sa.sa_flags |= SA_RESTART;
sa.sa_handler = alarm_handler;
sigaction (SIGALRM,&sa,NULL);
alarm(1);
while ((waitpid(pid,&i,0) != pid) && !WIFEXITED(i)) ;
if (WEXITSTATUS(i) == 0) fprintf (stderr,"\n");
exit (0);
}
#endif
fprintf (stderr,"* BD/DVD%sRW/-RAM format utility by <appro@fy.chalmers.se>, "
"version 7.1.\n",plusminus_locale());
for (i=1;i<argc;i++) {
if (*argv[i] == '-')
if (argv[i][1] == 'f') // -format|-force
{ force = 1;
if ((p=strchr(argv[i],'=')) && p[1]=='f') full=1;
}
else if (argv[i][1] == 'l') // -lead-out
force = compat = 1;
else if (argv[i][1] == 'b') // -blank
{ blank=0x11;
if ((p=strchr(argv[i],'=')) && p[1]=='f') blank=0x10;
force=1;
}
else if (argv[i][1] == 'p') // -pow
{ not_pow=1; // minus pow
}
else if (argv[i][1] == 's') // -ssa|-spare
{ force=ssa=1;
if ((p=strchr(argv[i],'=')))
{ if (p[1]=='n') ssa=-1; // =none
else if (p[3]=='n') ssa=1; // =min
else if (p[1]=='d') ssa=2; // =default
else if (p[3]=='x') ssa=3; // =max
else if (p[1]=='.' || (p[1]>='0' && p[1]<='9'))
{ char *s=NULL;
double a=strtod(p+1,&s);
if (s)
{ if (*s=='g' || *s=='G') a *= 1e9;
else if (*s=='m' || *s=='M') a *= 1e6;
else if (*s=='k' || *s=='K') a *= 1e3;
}
ssa = (int)(a/2e3); // amount of 2K
}
else ssa=0; // invalid?
}
}
else if (argv[i][1] == 'g') gui=1;
else usage(argv[0]);
#ifdef _WIN32
else if (argv[i][1] == ':')
#else
else if (*argv[i] == '/')
#endif
dev = argv[i];
else
usage (argv[0]);
}
if (dev==NULL) usage (argv[0]);
Scsi_Command cmd;
if (!cmd.associate(dev))
fprintf (stderr,":-( unable to open(\"%s\"): ",dev), perror (NULL),
exit(1);
cmd[0] = 0x12; // INQUIRY
cmd[4] = 36;
cmd[5] = 0;
if ((err=cmd.transport(READ,inq,36)))
sperror ("INQUIRY",err), exit (1);
if ((inq[0]&0x1F) != 5)
fprintf (stderr,":-( not an MMC unit!\n"),
exit (1);
cmd[0] = 0x46; // GET CONFIGURATION
cmd[8] = 8;
cmd[9] = 0;
if ((err=cmd.transport(READ,formats,8)))
sperror ("GET CONFIGURATION",err), exit (1);
mmc_profile = formats[6]<<8|formats[7];
blu_ray = ((mmc_profile&0xF0)==0x40);
if (mmc_profile!=0x1A && mmc_profile!=0x2A
&& mmc_profile!=0x14 && mmc_profile!=0x13
&& mmc_profile!=0x12
&& !blu_ray)
fprintf (stderr,":-( mounted media doesn't appear to be "
"DVD%sRW, DVD-RAM or Blu-ray\n",plusminus_locale()),
exit (1);
/*
* First figure out how long the actual list is. Problem here is
* that (at least Linux) USB units absolutely insist on accurate
* cgc.buflen and you can't just set buflen to arbitrary value
* larger than actual transfer length.
*/
int once=1;
do
{ cmd[0] = 0x23; // READ FORMAT CAPACITIES
cmd[8] = 4;
cmd[9] = 0;
if ((err=cmd.transport(READ,formats,4)))
{ if (err==0x62800 && once) // "MEDIUM MAY HAVE CHANGED"
{ cmd[0] = 0; // TEST UNIT READY
cmd[5] = 0;
cmd.transport(); // just swallow it...
continue;
}
sperror ("READ FORMAT CAPACITIES",err), exit (1);
}
} while (once--);
len = formats[3];
if (len&7 || len<8)
fprintf (stderr,":-( allocation length isn't sane\n"),
exit(1);
cmd[0] = 0x23; // READ FORMAT CAPACITIES
cmd[7] = (4+len)>>8; // now with real length...
cmd[8] = (4+len)&0xFF;
cmd[9] = 0;
if ((err=cmd.transport(READ,formats,4+len)))
sperror ("READ FORMAT CAPACITIES",err), exit (1);
if (len != formats[3])
fprintf (stderr,":-( parameter length inconsistency\n"),
exit(1);
if (mmc_profile==0x1A || mmc_profile==0x2A) // DVD+RW
{ for (i=8;i<len;i+=8) // look for "DVD+RW Full" descriptor
if ((formats [4+i+4]>>2) == 0x26) break;
}
else if (mmc_profile==0x12) // DVD-RAM
{ unsigned int v,ref;
unsigned char *f,descr=0x01;
int j;
switch (ssa)
{ case -1: // no ssa
for (ref=0,i=len,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == 0x00)
{ v=f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (v>ref) ref=v,i=j;
}
}
break;
case 1: // first ssa
for (i=8;i<len;i+=8)
if ((formats[4+i+4]>>2) == 0x01) break;
break;
case 2: // default ssa
descr=0x00;
case 3: // max ssa
for (ref=0xFFFFFFFF,i=len,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == descr)
{ v=f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (v<ref) ref=v,i=j;
}
}
break;
default:
i=8; // just grab the first descriptor?
break;
}
}
else if (mmc_profile==0x41) // BD-R
{ unsigned int max,min,cap;
unsigned char *f;
int j;
switch (ssa)
{ case -1: // no spare -> nothing to do
case 0:
exit (0);
break;
case 1: // min spare <- max capacity
i=len;
for (max=0,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == 0x32)
{ cap = f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (max < cap) max=cap,i=j;
}
}
break;
case 2: // default ssa
i=8; // just grab first descriptor
break;
case 3: // max, ~10GB, is too big to trust user
fprintf (stderr,"- -ssa=max is not supported for BD-R, "
"specify explicit size with -ssa=XXXG\n");
exit (1);
default:
i=len;
for (max=0,min=0xffffffff,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == 0x32)
{ cap = f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (max < cap) max=cap;
if (min > cap) min=cap;
}
}
if (max==0) break;
// for simplicity adjust spare size according to DL(!) rules
ssa += 8192, ssa &= ~16383; // i.e. in 32MB increments
f = formats+4;
capacity = f[0]<<24|f[1]<<16|f[2]<<8|f[3];
cap = capacity - ssa;
// place it within given boundaries
if (cap < min) cap = min;
else if (cap > max) cap = max;
i = 8;
f = formats+4+i;
f[0] = cap>>24;
f[1] = cap>>16;
f[2] = cap>>8;
f[3] = cap;
f[4] = 0x32<<2 | not_pow;
f[5] = 0;
f[6] = 0;
f[7] = 0;
break;
}
if (i<len)
{ f = formats+4+i;
f[4] &= ~3; // it's either SRM+POW ...
f[4] |= not_pow; // ... or SRM-POW
}
}
else if (mmc_profile==0x43) // BD-RE
{ unsigned int max,min,cap;
unsigned char *f;
int j;
switch (ssa)
{ case -1: // no spare
for (i=8;i<len;i+=8) // look for descriptor 0x31
if ((formats [4+i+4]>>2) == 0x31) break;
break;
case 0:
i = 8;
if ((formats[4+4]&3)==2)// same capacity for already formatted
{ f = formats+4+i;
memcpy (f,formats+4,4);
f[4] = 0x30<<2;
f[5] = 0;
f[6] = 0;
f[7] = 0;
}
break;
case 1: // min spare <- max capacity
i=len;
for (max=0,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == 0x30)
{ cap = f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (max < cap) max=cap,i=j;
}
}
break;
case 2: // default ssa
i=8; // just grab first descriptor
break;
case 3: // max spare <- min capacity
i=len;
for (min=0xffffffff,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == 0x30)
{ cap=f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (min > cap) min=cap,i=j;
}
}
break;
default:
i=len;
capacity=0;
for (max=0,min=0xffffffff,j=8;j<len;j+=8)
{ f = formats+4+j;
if ((f[4]>>2) == 0x30)
{ cap = f[0]<<24|f[1]<<16|f[2]<<8|f[3];
if (max < cap) max=cap;
if (min > cap) min=cap;
}
else if ((f[4]>>2) == 0x31)
capacity = f[0]<<24|f[1]<<16|f[2]<<8|f[3];
}
if (max==0 || capacity==0) break;
// for simplicity adjust spare size according to DL(!) rules
ssa += 8192, ssa &= ~16383; // i.e. in 32MB increments
cap = capacity - ssa;
// place it within given boundaries
if (cap < min) cap = min;
else if (cap > max) cap = max;
i = 8;
f = formats+4+i;
f[0] = cap>>24;
f[1] = cap>>16;
f[2] = cap>>8;
f[3] = cap;
f[4] = 0x30<<2;
f[5] = 0;
f[6] = 0;
f[7] = 0;
break;
}
if (i<len)
{ f = formats+4+i;
f[4] &= ~3;
if ((f[4]>>2)==0x30)
f[4] |= full?2:3; // "Full" or "Quick Certification"
}
}
else // DVD-RW
{ int descr=full?0x10:0x15;
for (i=8;i<len;i+=8) // look for "DVD-RW Quick" descriptor
if ((formats [4+i+4]>>2) == descr) break;
if (descr==0x15 && i==len)
{ fprintf (stderr,":-( failed to locate \"Quick Format\" descriptor.\n");
for (i=8;i<len;i+=8)// ... alternatively for "DVD-RW Full"
if ((formats [4+i+4]>>2) == 0x10) break;
}
}
if (i==len)
{ fprintf (stderr,":-( can't locate appropriate format descriptor\n");
if (blank) i=0;
else exit(1);
}
capacity = 0;
if (blu_ray)
{ capacity |= formats[4+0], capacity <<= 8;
capacity |= formats[4+1], capacity <<= 8;
capacity |= formats[4+2], capacity <<= 8;
capacity |= formats[4+3];
}
else
{ capacity |= formats[4+i+0], capacity <<= 8;
capacity |= formats[4+i+1], capacity <<= 8;
capacity |= formats[4+i+2], capacity <<= 8;
capacity |= formats[4+i+3];
}
if (mmc_profile==0x1A || mmc_profile==0x2A) // DVD+RW
fprintf (stderr,"* %.1fGB DVD+RW media detected.\n",
2048.0*capacity/1e9);
else if (mmc_profile==0x12) // DVD-RAM
fprintf (stderr,"* %.1fGB DVD-RAM media detected.\n",
2048.0*capacity/1e9);
else if (blu_ray) // BD
fprintf (stderr,"* %.1fGB BD media detected.\n",
2048.0*capacity/1e9);
else // DVD-RW
fprintf (stderr,"* %.1fGB DVD-RW media in %s mode detected.\n",
2048.0*capacity/1e9,
mmc_profile==0x13?"Restricted Overwrite":"Sequential");
lead_out = 0;
lead_out |= formats[4+0], lead_out <<= 8;
lead_out |= formats[4+1], lead_out <<= 8;
lead_out |= formats[4+2], lead_out <<= 8;
lead_out |= formats[4+3];
cmd[0] = 0x51; // READ DISC INFORMATION
cmd[8] = sizeof(dinfo);
cmd[9] = 0;
if ((err=cmd.transport(READ,dinfo,sizeof(dinfo))))
{ sperror ("READ DISC INFORMATION",err);
if (!force) exit(1);
memset (dinfo,0xff,sizeof(dinfo));
cmd[0] = 0x35;
cmd[9] = 0;
cmd.transport();
}
do_opc = ((dinfo[0]<<8|dinfo[1])<=0x20);
if (dinfo[2]&3) // non-blank media
{ if (!force)
{ if (mmc_profile==0x1A || mmc_profile==0x2A || mmc_profile==0x13 || mmc_profile==0x12)
fprintf (stderr,"- media is already formatted, lead-out is currently at\n"
" %d KiB which is %.1f%% of total capacity.\n",
lead_out*2,(100.0*lead_out)/capacity);
else
fprintf (stderr,"- media is not blank\n");
offer_options:
if (mmc_profile == 0x1A || mmc_profile == 0x2A)
fprintf (stderr,"- you have the option to re-run %s with:\n"
" -lead-out to elicit lead-out relocation for better\n"
" DVD-ROM compatibility, data is not affected;\n"
" -force to enforce new format (not recommended)\n"
" and wipe the data.\n",
argv[0]);
else if (mmc_profile == 0x12)
fprintf (stderr,"- you have the option to re-run %s with:\n"
" -format=full to perform full (lengthy) reformat;\n"
" -ssa[=none|default|max]\n"
" to grow, eliminate, reset to default or\n"
" maximize Supplementary Spare Area.\n",
argv[0]);
else if (mmc_profile == 0x43)
fprintf (stderr,"- you have the option to re-run %s with:\n"
" -format=full to perform (lengthy) Full Certification;\n"
" -ssa[=none|default|max|XXX[GM]]\n"
" to eliminate or adjust Spare Area.\n",
argv[0]);
else if (blu_ray) // BD-R
fprintf (stderr,"- BD-R can be pre-formatted only once\n");
else
{ fprintf (stderr,"- you have the option to re-run %s with:\n",
argv[0]);
if (i) fprintf (stderr,
" -force[=full] to enforce new format or mode transition\n"
" and wipe the data;\n");
fprintf (stderr," -blank[=full] to change to Sequential mode.\n");
}
exit (0);
}
else if (cmd.umount())
perror (errno==EBUSY ? ":-( unable to proceed with format" :
":-( unable to umount"),
exit (1);
}
else
{ if (mmc_profile==0x14 && blank==0 && !force)
{ fprintf (stderr,"- media is blank\n");
fprintf (stderr,"- given the time to apply full blanking procedure I've chosen\n"
" to insist on -force option upon mode transition.\n");
exit (0);
}
else if (mmc_profile==041 && !force)
{ fprintf (stderr,"- media is blank\n");
fprintf (stderr,"- as BD-R can be pre-formance only once, I've chosen\n"
" to insist on -force option.\n");
}
force = 0;
}
if (((mmc_profile == 0x1A || mmc_profile == 0x2A) && blank)
|| (mmc_profile != 0x1A && compat)
|| (mmc_profile != 0x12 && mmc_profile != 0x43 && ssa) )
{ fprintf (stderr,"- illegal command-line option for this media.\n");
goto offer_options;
}
else if ((mmc_profile == 0x1A || mmc_profile == 0x2A) && full)
{ fprintf (stderr,"- unimplemented command-line option for this media.\n");
goto offer_options;
}
#if defined(__unix) || defined(__unix__)
/*
* You can suspend, terminate, etc. the parent. We will keep on
* working in background...
*/
setsid();
signal(SIGHUP,SIG_IGN);
signal(SIGINT,SIG_IGN);
signal(SIGTERM,SIG_IGN);
#endif
if (compat && force) str="relocating lead-out";
else if (blank) str="blanking";
else str="formatting";
if (gui) gui_action=str;
else fprintf (stderr,"* %s .",str);
*progress = 1;
// formats[i] becomes "Format Unit Parameter List"
formats[i+0] = 0; // "Reserved"
formats[i+1] = 2; // "IMMED" flag
formats[i+2] = 0; // "Descriptor Length" (MSB)
formats[i+3] = 8; // "Descriptor Length" (LSB)
handle_events(cmd);
if (mmc_profile==0x1A || mmc_profile==0x2A) // DVD+RW
{ if (compat && force && (dinfo[2]&3))
formats[i+4+0]=formats[i+4+1]=formats[i+4+2]=formats[i+4+3]=0,
formats[i+4+7] = 1; // "Restart format"
cmd[0] = 0x04; // FORMAT UNIT
cmd[1] = 0x11; // "FmtData" and "Format Code"
cmd[5] = 0;
if ((err=cmd.transport(WRITE,formats+i,12)))
sperror ("FORMAT UNIT",err), exit(1);
if (wait_for_unit (cmd,progress)) exit (1);
if (!compat)
{ cmd[0] = 0x5B; // CLOSE TRACK/SESSION
cmd[1] = 1; // "IMMED" flag on
cmd[2] = 0; // "Stop De-Icing"
cmd[9] = 0;
if ((err=cmd.transport()))
sperror ("STOP DE-ICING",err), exit(1);
if (wait_for_unit (cmd,progress)) exit (1);
}
cmd[0] = 0x5B; // CLOSE TRACK/SESSION
cmd[1] = 1; // "IMMED" flag on
cmd[2] = 2; // "Close Session"
cmd[9] = 0;
if ((err=cmd.transport()))
sperror ("CLOSE SESSION",err), exit(1);
if (wait_for_unit (cmd,progress)) exit (1);
}
else if (mmc_profile==0x12) // DVD-RAM
{ cmd[0] = 0x04; // FORMAT UNIT
cmd[1] = 0x11; // "FmtData"|"Format Code"
cmd[5] = 0;
formats[i+1] = 0x82; // "FOV"|"IMMED"
if ((formats[i+4+4]>>2) != 0x01 && !full)
formats[i+1] |= 0x20,// |"DCRT"
cmd[1] |= 0x08; // |"CmpLst"
if ((err=cmd.transport(WRITE,formats+i,12)))
sperror ("FORMAT UNIT",err), exit(1);
if (wait_for_unit (cmd,progress)) exit(1);
}
else if (mmc_profile==0x43) // BD-RE
{ cmd[0] = 0x04; // FORMAT UNIT
cmd[1] = 0x11; // "FmtData"|"Format Code"
cmd[5] = 0;
formats[i+1] = 0x82; // "FOV"|"IMMED"
if (full && (formats[i+4+4]>>2)!=0x31)
formats[i+4+4] |= 2;// "Full Certificaton"
else if ((formats[i+4+4]>>2)==0x30)
formats[i+4+4] |= 3;// "Quick Certification"
if ((err=cmd.transport(WRITE,formats+i,12)))
sperror ("FORMAT UNIT",err), exit(1);
if (wait_for_unit (cmd,progress)) exit(1);
}
else if (mmc_profile==0x41) // BD-R
{ cmd[0] = 0x04; // FORMAT UNIT
cmd[1] = 0x11; // "FmtData"|"Format Code"
cmd[5] = 0;
formats[i+1] = 0x2; // IMMED"
if ((err=cmd.transport(WRITE,formats+i,12)))
sperror ("FORMAT UNIT",err), exit(1);
if (wait_for_unit (cmd,progress)) exit(1);
}
else // DVD-RW
{ page05_setup (cmd,mmc_profile);
if (do_opc)
{ cmd[0] = 0x54; // SEND OPC INFORMATION
cmd[1] = 1; // "Perform OPC"
cmd[9] = 0;
cmd.timeout(120); // NEC units can be slooo...w
if ((err=cmd.transport()))
{ if (err==0x17301) // "POWER CALIBRATION AREA ALMOST FULL"
fprintf (stderr,":-! WARNING: Power Calibration Area "
"is almost full\n");
else
{ sperror ("PERFORM OPC",err);
if ((err&0x0FF00)==0x07300 && (err&0xF0000)!=0x10000)
exit (1);
/* The rest of errors are ignored, see groisofs_mmc.cpp
* for further details... */
}
}
}
if (blank) // DVD-RW blanking procedure
{ cmd[0] = 0xA1; // BLANK
cmd[1] = blank;
cmd[11] = 0;
if ((err=cmd.transport()))
sperror ("BLANK",err), exit(1);
if (wait_for_unit (cmd,progress)) exit (1);
}
else // DVD-RW format
{ if ((formats[i+4+4]>>2)==0x15) // make it really quick
formats[i+4+0]=formats[i+4+1]=formats[i+4+2]=formats[i+4+3]=0;
cmd[0] = 0x04; // FORMAT UNIT
cmd[1] = 0x11; // "FmtData" and "Format Code"
cmd[5] = 0;
if ((err=cmd.transport(WRITE,formats+i,12)))
sperror ("FORMAT UNIT",err), exit(1);
if (wait_for_unit (cmd,progress)) exit (1);
cmd[0] = 0x35; // FLUSH CACHE
cmd[9] = 0;
cmd.transport ();
}
}
pioneer_stop (cmd,progress);
#if 0
cmd[0] = 0x1E; // ALLOW MEDIA REMOVAL
cmd[5] = 0;
if (cmd.transport ()) return 1;
cmd[0] = 0x1B; // START/STOP UNIT
cmd[4] = 0x2; // "Eject"
cmd[5] = 0;
if (cmd.transport()) return 1;
cmd[0] = 0x1B; // START/STOP UNIT
cmd[1] = 0x1; // "IMMED"
cmd[4] = 0x3; // "Load"
cmd[5] = 0;
cmd.transport ();
#endif
return 0;
}

1130
dvd+rw-mediainfo.cpp Normal file

File diff suppressed because it is too large Load Diff

447
dvd+rw-tools.spec Normal file
View File

@ -0,0 +1,447 @@
Summary: Toolchain for mastering recordable BD and DVD media
Name: dvd+rw-tools
Version: 7.1
Release: 1
License: GPL
Group: Applications/Multimedia
Source: http://fy.chalmers.se/~appro/linux/DVD+RW/tools/dvd+rw-tools-%{version}.tar.gz
URL: http://fy.chalmers.se/~appro/linux/DVD+RW/
Requires: mkisofs >= 1.10
BuildRoot: %{_tmppath}/%{name}-root
BuildRequires: kernel-headers wget
%description
Collection of tools to master Blu-ray Disc and DVD+RW/+R/-R/-RW media.
For further information see http://fy.chalmers.se/~appro/linux/DVD+RW/.
%prep
%setup -q
%build
make
[ -f index.html ] || wget -nd http://fy.chalmers.se/~appro/linux/DVD+RW/
%install
[ %{buildroot} == / ] || rm -rf %{buildroot}
cd %{_builddir}/%{name}-%{version}
make prefix=%{buildroot}%{_prefix} manprefix=%{buildroot}%{_mandir} install
mkdir -p %{buildroot}%{_docdir}/%{name}-%{version}-%{release}
cp -a index.html %{buildroot}%{_docdir}/%{name}-%{version}-%{release}
%clean
[ %{buildroot} == / ] || rm -rf %{buildroot}
%files
%defattr(-,root,root)
%{_prefix}/bin/*
%doc %{_docdir}/%{name}-%{version}-%{release}
%doc %{_mandir}/man1/*
%changelog
* Mon Mar 3 2008 Andy Polyakov <appro@fy.chalmers.se>
- 7.1 release;
- Linux: allow compilation with non-substitution 2.6 kernel headers;
- Linux: not all 2.4 filesystem types support direct I/O;
- Linux: lock corresponding /dev/srN;
- use PTHREAD_STACK_MIN when creating threads;
- use _SC_PHYS_PAGES instead of _SC_AVPHYS_PAGES when calculating
ring buffer size limit;
- Mac OS X: allow compilation on 10.5;
- human-readable sense code transcription;
- Solaris: privileges, authorization and hald awareness;
- in order to minimize swap reservations mmap ring buffer with
MAP_SHARED;
- add -F/-free-space option displaying next session offset and
media capacity, which facilitates free space calculation [by
suggestion from Bacula project];
- allow session to cross 4GB boundary even on single-layer media
[by request from Bacula project];
- HP-UX: fix compilation warnings;
- refine x73xx error treatment;
- handle deferred errno from reader thread;
- return non-zero exit status more aggressively;
* Sun Sep 24 2006 Andy Polyakov <appro@fy.chalmers.se>
- 7.0 release;
- Blu-ray Disc support [upon release tested with Panasonic SW-5582];
- Mac OS X 10>=2 support [upon release tested on 10.4 only];
- Linux: copy <linux/raw.h> definitions directly into application
code in order to secure backward compatibility;
- Linux: overcome 16MB O_DIRECT limitaton for NFS client;
- limit ring buffer size to 1/4 of RAM;
- copy volume descriptors if -C was specified with -M /dev/dvd=image
[by request from K3b];
- -use-the-force-luke=spare[:none|min] to control blank BD pre-format
[for finer control use dvd+rw-format];
- some units, e.g. Lite-on SOHW-1693S, seem to fire off OPC already
upon Layer Break command, therefore longer timeout is required;
- Linux: deploy BLKFLSBUF to avoid media reloads when possible;
- add unit buffer utilization indicator [by request from K3b];
* Sun Jan 29 2006 Andy Polyakov <appro@fy.chalmers.se>
- 6.1 release;
* Thu Jan 26 2006 Andy Polyakov <appro@fy.chalmers.se>
- permit tracksize to be not divisible by 32KB in DAO mode;
* Wed Jan 25 2006 Andy Polyakov <appro@fy.chalmers.se>
- Linux: utilize O_EXCL flag [but do see commentary in source code!];
- Treat only x73xx OPC errors as fatal;
- Fix typo in -speed scaling code;
* Fri Jan 20 2006 Andy Polyakov <appro@fy.chalmers.se>
- ± localization;
* Thu Jan 19 2006 Andy Polyakov <appro@fy.chalmers.se>
- Linux: default rlimit for locked pages is way too small [note
that in order to allocate ring buffer larger than default 32MB
through command line option, you have to increase memorylocked
limit accordingly prior application start];
- make -use-the-force-luke=noload, which leaves tray open, work;
- DEFAULT_BUF_SIZE_MB is a macro, which can be redefined at
compile time with 'make WARN=-DDEFAULT_BUF_SIZE_MB=[16|64]' to
change the default ring buffer size;
* Tue Jan 17 2006 Andy Polyakov <appro@fy.chalmers.se>
- FreeBSD: improve backward binary compatibility;
* Mon Jan 16 2006 Andy Polyakov <appro@fy.chalmers.se>
- 6.0 release;
* Fri Jan 13 2006 Andy Polyakov <appro@fy.chalmers.se>
- -use-the-force-luke=noopc to skip OPC altogether;
- implement 50% check for DVD-R DL;
- demote failure to change speed to warning;
* Sun Jan 8 2006 Andy Polyakov <appro@fy.chalmers.se>
- refine Pioneer strategies;
- write procedure to recognize "IN PROCESS OF BECOMING READY"
[observed on newer Lite-On 1693S firmware and NEC];
- allow for more intuitive interpretation of -speed factor with
units returning minimal velocity other than 1x;
* Fri Jan 6 2006 Andy Polyakov <appro@fy.chalmers.se>
- multi-threaded design;
- asynchronous ring buffer implementation;
- Win32/Mingw32 port;
* Mon Dec 5 2005 Andy Polyakov <appro@fy.chalmers.se>
- version harmonization in preparation for 6.0 release;
* Sun Nov 28 2004 Andy Polyakov <appro@fy.chalmers.se>
- DVD-R Dual Layer DAO and Incremental support;
* Sun Sep 26 2004 Andy Polyakov <appro@fy.chalmers.se>
- fix for DVD+R recordings in Samsung TS-H542A;
* Sat Aug 28 2004 Andy Polyakov <appro@fy.chalmers.se>
- 5.21.4.10.8 release;
* Wed Aug 25 2004 Andy Polyakov <appro@fy.chalmers.se>
- Linux: fix for kernel version 2.6>=8, 2.6.8 itself is deficient,
but the problem can be worked around by installing this version
set-root-uid;
* Thu Jul 15 2004 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.20.4.10.8 release;
* Tue Jul 13 2004 Andy Polyakov <appro@fy.chalmers.se>
- Layer Break position sanity check with respect to dataset size;
- #if directive to get rid of sudo check at compile time with
'make WARN=-DI_KNOW_ALL_ABOUT_SUDO';
* Mon Jul 12 2004 Andy Polyakov <appro@fy.chalmers.se>
- speed verification issue with 8x AccessTek derivatives addressed;
- -use-the-force-luke=noload to leave tray ejected at the end;
- allow to resume incomplete sessions recorded with -M option;
* Sat Jul 3 2004 Andy Polyakov <appro@fy.chalmers.se>
- -use-the-force-luke=break:size to set Layer Break position for
Double Layer recordings;
* Fri Jun 25 2004 Andy Polyakov <appro@fy.chalmers.se>
- handle non-fatal OPC errors;
- DVD+R Double Layer support;
- -use-the-force-luke=4gms to allow ISO9660 directory structures
to cross 4GB boundary, the option is effective only with DVD+R DL
and for data to be accessible under Linux isofs kernel patch is
required;
* Wed May 26 2004 Andy Polyakov <appro@fy.chalmers.se>
- HP-UX: inconsistency between /dev/rdsk and /dev/rscsi names;
* Wed Apr 21 2004 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.19-1 hotfix to address "flushing cache takes forever;
* Sat Apr 18 2004 Andy Polyakov <appro@fy.chalmers.se>
- DVD-RAM reload if recorded with -poor-man;
- -use-the-force-luke=wrvfy for WRITE AND VERIFY(10);
- "flushing cache" takes forever;
- dvd+rw-format 4.10: add support for DVD-RAM;
* Sat Apr 10 2004 Andy Polyakov <appro@fy.chalmers.se>
- 5.19.4.9.7 release;
* Sun Apr 4 2004 Andy Polyakov <appro@fy.chalmers.se>
- LG GSA-4081B fails to "SET STREAMING" with "LBA OUT OF RANGE" for
DVD+RW media, but not e.g. DVD-R;
- dvd+rw-booktype: BTC support;
* Sat Apr 3 2004 Andy Polyakov <appro@fy.chalmers.se>
- make DVD-RAM work in "poor-man" mode;
- average write speed report at the end of recording;
* Fri Apr 2 2004 Andy Polyakov <appro@fy.chalmers.se>
- dvd+rw-format 4.9: permit for DVD-RW blank even if format descriptors
are not present;
* Thu Apr 1 2004 Andy Polyakov <appro@fy.chalmers.se>
- Solaris: get rid of media reload, which made it possible to improve
volume manager experience as well;
- address speed verification issues with NEC ND-2500 and Plextor
PX-708A;
* Mon Mar 22 2004 Andy Polyakov <appro@fy.chalmers.se>
- dvd+rw-tools-5.18.4.8.6: www.software.hp.com release;
* Sat Mar 20 2004 Andy Polyakov <appro@fy.chalmers.se>
- IRIX: IRIX 6.x port is added;
* Wed Feb 11 2004 Andy Polyakov <appro@fy.chalmers.se>
- minimize amount of compiler warnings on 64-bit platforms;
- skip count-down if no_tty_check is set;
- -use-the-force-luke=tracksize:size option by suggestion from K3b;
- Linux: fix for "Bad file descriptor" with DVD+RW kernel patch;
* Tue Jan 20 2004 Andy Polyakov <appro@fy.chalmers.se>
- refuse to run if ${SUDO_COMMAND} is set;
* Wed Jan 14 2004 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.17: fix for COMMAND SEQUENCE ERROR in the beginning of
DVD-recording;
- drop privileges prior mkisofs -version;
* Tue Jan 13 2004 Andy Polyakov <appro@fy.chalmers.se>
- the last speed change required adaptations for Pioneer and LG units,
which don't/fail to provide current write speed through GET
PERFORMANCE despite the fact that the command is mandatory;
- HP-UX: retain root privileges in setup_fds, SIOC_IO requires them;
* Sun Jan 4 2004 Andy Polyakov <appro@fy.chalmers.se>
- switch to GET PERFORMANCE even for current write speed (most
notably required for NEC and derivatives);
* Tue Dec 30 2003 Andy Polyakov <appro@fy.chalmers.se>
- Linux: fix for /proc/sys/dev/cdrom/check_media set to 1;
- HP-UX: INQUIRY buffer is required to be 128 bytes, well, "required"
is wrong word in this context, as it's apparently a kernel bug
addressed in PHKL_30038 (HPUX 11.11) and PHKL_30039 (HPUX 11.23);
* Fri Dec 26 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.16: brown-bag bug in "LONG WRITE IN PROGRESS" code path;
* Mon Dec 22 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.15: confusing output when DAO mode is manually engaged
and DVD-RW media is minimally blanked;
- complement -use-the-force-luke=dao[:size] to arrange for piping
non-iso images in DAO mode (size is to be expressed in 2KB chunks);
- Pioneer DVR-x06 apparently needs larger timeout to avoid "the LUN
appears to be stuck" message in the beginning of DAO recording;
- HP-UX: fix-up umount code;
- HP-UX: make sure user doesn't pass /dev/rscsi/cXtYlZ, they should
stick to /dev/rdsk/cXtYdZ;
- implement -use-the-force-luke=seek:N -Z /dev/dvd=image to arrange
for 'builtin_dd if=image of=/dev/dvd obs=32k seek=N/16' (note that
N is expected to be expressed in 2KB chunks);
- skip overwrite check for blank media to avoid read errors at start,
which reportedly may cause bus reset in some configurations;
- make get_mmc_profile load media, explicit media load used to be on
per platform basis, while it doesn't have to;
- postpone handle_events till after dry-run checkpoint;
- error reporting revised;
- Optorite seems to insist on resuming suspended DVD+RW format, at
least it's apparently the only way to get *reliable* results
(formally this contradicts specification, which explicitly states
that format is to be resumed automatically and transparently);
- FreeBSD: FreeBSD 5-CURRENT since 2003-08-24, including 5.2 fails
to pull sense data automatically, at least for ATAPI transport,
so I reach for it myself (it's apparently a kernel bug, which
eventually will be fixed, but I keep the workaround code just in
case);
- -speed option in DVD+ context is enabled, upon release tested with
Plextor PX-708A;
- make builtin_dd print amount of transferred data, together with
-use-the-force-luke=seek:N it's easier to maintain "tar-formatted"
rewritable media;
- dvd+rw-format 4.8: DVD-RW format fails if preceeded by dummy
recording;
- make sure we talk to MMC unit, be less intrusive;
- unify error reporting;
- permit for -lead-out even for blank DVD+RW, needed(?) for SANYO
derivatives;
- dvd+rw-booktype 5: support for Benq derivatives;
* Tue Dec 2 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.14: TEAC DV-W50D and Lite-On LDW-811S failed to set
recording velocity, deploy GET PERFORMANCE/SET STREAMING commands;
- Lite-On LDW-811S returns 0s in Write Speed descriptors in page 2A,
this would cause a problem if DVD+ speed control was implemented;
* Thu Nov 20 2003 Andy Polyakov <appro@fy.chalmers.se>
- Solaris: use large-file API in setup_fds;
- HP-UX: HP-UX support is contributed by HP;
- block signals in the beginning of recording, formally it shouldn't
be necessary, but is apparently needed for some units (is it?);
- prepare code for -speed even in DVD+ context, need a test-case...
* Sun Nov 2 2003 Andy Polyakov <appro@fy.chalmers.se>
- progress indicator process was orphaned if -Z /dev/cdrom=file.iso
terminated prematurely;
- -overburn -Z /dev/cdrom=file.iso printed two "ignored" messages;
* Thu Oct 23 2003 Andy Polyakov <appro@fy.chalmers.se>
- '| growisofs -Z /dev/cdrom=/dev/fd/0' failed with
"already carries isofs" even when running interactively, so I check
on /dev/tty instead of isatty(0);
- error output was confusing when overburn condition was raised in
dry-run mode;
- more sane default drain buffer size to minimize system load when
unit fails to return usable buffer utilization statistics under
"LONG WRITE IN PROGRESS" condition;
* Wed Oct 1 2003 Andy Polyakov <appro@fy.chalmers.se>
- LG GSA-4040B fails to auto-format DVD+RW blanks;
* Mon Sep 15 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.13: support for Panasonic/MATSUSHITA DVD-RAM LF-D310;
* Sat Sep 6 2003 Andy Polyakov <appro@fy.chalmers.se>
- RPM build fix-ups, no version change;
* Fri Aug 31 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.12: [major] issue with MODE SENSE/SELECT on SANYO
derivatives, such as Optorite, is addressed;
- Linux can't open(2) a socket by /dev/fd/N, replace it with dup(2);
- more relaxed command line option parsing and simultaneously a
zealous check to make sure that no mkisofs options are passed
along with -[ZM] /dev/cdrom=image;
- report I/O error if input stream was less than 64K;
- -M /dev/cdrom=/dev/zero didn't relocate the lead-out in DVD-RW
Restricted Overwrite;
* Fri Aug 15 2003 Andy Polyakov <appro@fy.chalmers.se>
- single Pioneer DVR-x06 user reported that very small fraction of
his recordings get terminted with "LONG WRITE IN PROGRESS," even
though growisofs explicitly reserves for this condition... It
turned out that at those rare occasions unit reported a lot of free
buffer space, which growisofs treated as error condition. It's not
clear if it's firmware deficiency, but growisofs reserves even for
this apparently rare condition now.
- dvd+rw-format 4.7: when formatting DVD+RW, Pioneer DVR-x06 remained
unaccessible for over 2 minutes after dvd+rw-format exited and user
was frustrated to poll the unit himself, now dvd+rw-format does it for
user;
* Sun Aug 3 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.11: authorship statement in -version output;
- make speed_factor floating point and print "Current Write Speed"
factor for informational purposes;
- Pioneer DVR-x06 exhibited degraded performance when recording DVD+;
- Pioneer DVR-x06 failed to complete DVD+ recording gracefully;
- alter set-root-uid behaviour under Linux from "PAM-junky" to more
conservative one;
- dvd+rw-format 4.6: -force to ignore error from READ DISC INFORMATION;
- -force was failing under FreeBSD with 'unable to unmount';
- undocumented -gui flag to ease progress indicator parsing for
GUI front-ends;
* Fri Jul 14 2003 Andy Polyakov <appro@fy.chalmers.se>
- dvd+rw-format 4.5: increase timeout for OPC, NEC multi-format
derivatives might require more time to fulfill the OPC procedure;
- growisofs 5.10: increase timeout for OPC, NEC multi-format
derivatives might require more time to fulfill the OPC procedure;
- extended syntax for -use-the-force-luke option, it's now possible
to engage DVD-R[W] dummy mode by -use-the-force-luke=[tty,]dummy
for example, where "tty" substitutes for the original non-extended
option meaning, see the source for more easter eggs;
- FreeBSD: compile-time option to pass -M /dev/fd/0 to mkisofs to
make life easier for those who mount devfs, but not fdescfs;
- eliminate potential race conditions;
- avoid end-less loop if no media was in upon tray load;
- interpret value of MKISOFS environment variable as absolute path
to mkisofs binary;
- to facilitate for GUI front-ends return different exit codes, most
notably exit value of 128|errno denotes a fatal error upon program
startup [messages worth popping up in a separate modal dialog
perhaps?], errno - fatal error during recording and 1 - warnings
at exit;
- to facilitate for GUI front-ends auto-format blank DVD+RW media;
- Linux: fix for failure to copy volume descriptors when DVD-RW
Restricted Overwrite procedure is applied to patched kernel;
- FreeBSD: growisofs didn't close tray upon startup nor did the rest
of the tools work with open tray;
- bark at -o option and terminate execution, the "problem" was that
users seem to misspell -overburn once in a while, in which case it
was passed down to mkisofs and an iso-image was dumped to current
working directory instead of media;
- generalize -M /dev/cdrom=file.iso option, but if file.iso is not
/dev/zero, insist on sane -C argument to be passed prior -M and
double-verify the track starting address;
* Tue Jun 20 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.9: some [SONY] firmwares make it impossible to tell
apart minimally and fully blanked media, so we need a way to engage
DAO manually [in DVD-RW]... let's treat multiple -dvd-compat options
as "cry" for DAO;
- refuse to finalize even DVD-R media with -M flag (advise to fill
it up with -M /dev/cdrom=/dev/zero too), apparently DVD-units
[or is it just SONY?] also "misplace" legacy lead-out in the same
manner as DVD+units;
- oops! DAO hung at >4MB buffer because of sign overflow;
- couple of human-readable error messages in poor_mans_pwrite64;
- work around Plextor firmware deficiency which [also] manifests as
end-less loop upon startup;
* Wed Jun 14 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.8: elder Ricoh firmwares seem to report events
differently, which triggered growisofs and dvd+rw-format to
end-less loop at startup [event handling was introduced in 5.6
for debugging purposes];
- int ioctl_fd is transformed to void *ioctl_handle to facilitate
port to FreeBSD;
- FreeBSD support contributed by Matthew Dillon;
- volume descriptors from second session were discarded in
Restricted Overwrite since 5.6;
* Sun Jun 8 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.7: Solaris 2.x USB workaround;
- 15 min timeout for FLUSH CACHE in DVD-RW DAO;
- revalidate recording speed;
- load media upon start-up (Linux used to auto-close tray upon open,
but not the others, which is why this functionality is added so
late);
- dvd+rw-mediainfo: DVD-R[W] MediaID should be printed now;
* Sat May 31 2003 Andy Polyakov <appro@fy.chalmers.se>
- Solaris support is merged;
* Mon May 26 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.6: unconditional exit in set-root-uid assistant, mostly
for aesthetic reasons;
- support for DVD-RW DAO recordings (whenever Pioneer-ish Quick
Format is not an option, DAO should fill in for it, as it's the
only recording strategy applicable after *minimal* blanking
procedure);
- support for SG_IO pass-through interface, or in other words
support for Linux 2>=5;
- 'growisofs -M /dev/cdrom=/dev/zero', this is basically a counter-
intuitive kludge assigned to fill up multi-session write-once
media for better compatibility with DVD-ROM/-Video units, to keep
it mountable [in the burner unit] volume descriptors from previous
session are copied to the new session;
- disable -dvd-compat with -M option and DVD+R, advice to fill up
the media as above instead;
- postpone Write Page setup all the way till after dry_run check;
- if recording to write-once media is terminated by external event,
leave the session opened, so that the recording can be resumed
(though no promises about final results are made, it's just that
leaving it open makes more sense than to close the session);
- ask unit to perform OPC if READ DISC INFORMATION doesn't return
any OPC descriptors;
- get rid of redundant Quick Grow in Restricted Overwrite;
- dvd+rw-formwat 4.4: support for -force=full in DVD-RW context;
- ask unit to perform OPC if READ DISC INFORMATION doesn't return
any OPC descriptors;
- new dvd+rw-mediainfo utility for debugging purposes;
* Thu May 1 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.5: fix for ENOENT at unmount, I should have called myself
with execlp, not execl;
- security: chdir to / in set-root-uid assistant;
- use /proc/mounts instead of MOUNTED (a.k.a. /etc/mtab) in Linux
umount code;
- changed to 'all' target in Makefile to keep NetBSD people happy;
* Sun Apr 20 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.4: setup_fds is introduced to assist ports to another
platforms;
- set-root-uid assistant code directly at entry point (see main());
- OpenBSD/NetBSD port added;
* Thu Mar 27 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.4: split first write to avoid "empty DMA table?" in
kernel log;
- dvd+rw-format 4.3: natural command-line restrictions;
* Thu Mar 20 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.3: refuse to burn if session starts close to or beyond
the 4GB limit (due to limitation of Linux isofs implementation).
- media reload is moved to growisofs from dvd+rw-format.
- dry_run check is postponed all the way till the first write.
* Sat Mar 15 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.3/dvd+rw-format 4.2: support for DVD-RW Quick Format,
upon release tested with Pioneer DVR-x05.
- bug in DVD+RW overburn protection code fixed.
* Thu Feb 27 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.2: brown-bag bug in "LONG WRITE IN PROGRESS" handling
code fixed.
* Mon Feb 1 2003 Andy Polyakov <appro@fy.chalmers.se>
- code to protect against overburns.
- progress indicator to display recording velocity.
- re-make it work under Linux 2.2 kernel.
* Tue Jan 14 2003 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.1: support for DVD-R[W] writing speed control.
- dvd+rw-booktype 4: see the source.
* Tue Nov 26 2002 Andy Polyakov <appro@fy.chalmers.se>
- growisofs 5.0: support for DVD-R[W].
- dvd+rw-format 4.0: support for DVD-RW.
- growisofs 4.2: workaround for broken DVD+R firmwares (didn't make
public by itself).
* Thu Nov 4 2002 Andy Polyakov <appro@fy.chalmers.se>
- Minor growisofs update. Uninitialized errno at exit when
-Z /dev/scd0=image.iso is used.
* Thu Nov 3 2002 Andy Polyakov <appro@fy.chalmers.se>
- Initial packaging. Package version is derived from growisofs,
dvd+rw-format and dvd+rw-booktype version. 4.0.3.0.3 means
growisofs 4.0, dvd+rw-format 3.0 dvd+rw-booktype 3.

143
dvd-ram-control.cpp Normal file
View File

@ -0,0 +1,143 @@
#include "transport.hxx"
int main (int argc,char *argv[])
{ Scsi_Command cmd;
unsigned char buf[128],erb=0;
int err,i,rdonly=0;
const char *dev=NULL;
for (i=1;i<argc;i++)
{ if (!strncmp (argv[i],"-arre",4)) erb|=0x40;
else if (!strncmp (argv[i],"-awre",4)) erb|=0x80;
else if (!strncmp (argv[i],"-rdonly",4)) rdonly=1;
else if (!strncmp (argv[i],"-rdwr",4)) rdonly=-1;
else if (!strncmp (argv[i],"-rw",3)) rdonly=-1;
else if (!strncmp (argv[i],"-wronly",3)) rdonly=-1;
else dev=argv[i];
}
if (!(dev && (erb || rdonly)))
{ fprintf (stderr,"usage: %s [-arre] [-awre] [-rdonly|-rdwr] /dev/dvd\n",
argv[0]);
return 1;
}
if (!cmd.associate (dev))
{ fprintf (stderr,"%s: unable to open: ",dev), perror (NULL);
return 1;
}
cmd[0] = 0x12; // INQUIRY
cmd[4] = 36;
cmd[5] = 0;
if ((err=cmd.transport(READ,buf,36)))
{ sperror ("INQUIRY",err);
return 1;
}
if ((buf[0]&0x1F) != 5)
{ fprintf (stderr,":-( not an MMC unit!\n");
return 1;
}
#if 0
cmd[0]=0x46; // GET CONFIGURATION
cmd[1]=1;
cmd[8]=8;
cmd[9]=0;
if ((err=cmd.transport(READ,buf,8)))
{ sperror ("GET CONFIGURATION",err);
return 1;
}
if ((buf[6]<<8|buf[7]) != 0x12)
{ fprintf (stderr,":-( not DVD-RAM!\n");
return 1;
}
#endif
if (erb) do
{ unsigned char page01[8+12];
cmd[0]=0x5A; // MODE SENSE
cmd[1]=0x08; // "Disable Block Descriptors"
cmd[2]=1; // Page 01
cmd[8]=sizeof(page01);
if ((err=cmd.transport(READ,page01,sizeof(page01))))
{ sperror("MODE SENSE",err); return 1; }
if ((page01[8+2]&erb) == erb)
{ printf ("A[RW]RE bit is set already.\n");
break;
}
memset (page01,0,8);
page01[8+2]|=erb; // A[WR]RE on
cmd[0]=0x55; // MODE SELECT
cmd[1]=0x10; // conformant
cmd[8]=sizeof(page01);
cmd[9]=0;
if ((err=cmd.transport(WRITE,page01,sizeof(page01))))
{ sperror("MODE SELECT",err); return 1; }
// Verify settings...
cmd[0]=0x5A; // MODE SENSE
cmd[1]=0x08; // "Disable Block Descriptors"
cmd[2]=1; // Page 01
cmd[8]=sizeof(page01);
if ((err=cmd.transport(READ,page01,sizeof(page01))))
{ sperror("MODE SENSE",err); return 1; }
if ((page01[8+2]&erb) != erb)
{ fprintf (stderr,":-( failed to set A[RW]RE bit.\n");
return 1;
}
} while (0);
if (rdonly) do
{ unsigned char dvd_C0[8];
cmd[0]=0xAD; // READ DVD STRUCTURE
cmd[7]=0xC0;
cmd[9]=sizeof(dvd_C0);
cmd[11]=0;
if ((err=cmd.transport(READ,dvd_C0,sizeof(dvd_C0))))
{ sperror("READ DVD STRUCTURE#C0",err); return 1; }
if (rdonly>0 && (dvd_C0[4]&0x02))
{ printf ("The disc is write protected already.\n");
break;
}
else if (rdonly<0 && !(dvd_C0[4]&0x02))
{ printf ("The disc is unprotected already.\n");
break;
}
memset (dvd_C0,0,sizeof(dvd_C0));
dvd_C0[1]=6;
if (rdonly>0) dvd_C0[4]|=2; // "PWP" on
else dvd_C0[4]&=~2; // "PWP" off
cmd[0]=0xBF; // SEND DVD STRUCTURE
cmd[7]=0xC0;
cmd[9]=sizeof(dvd_C0);
cmd[11]=0;
if ((err=cmd.transport(WRITE,dvd_C0,sizeof(dvd_C0))))
{ sperror("SEND DVD STRUCTURE#C0",err); return 1; }
// Verify...
cmd[0]=0xAD; // READ DVD STRUCTURE
cmd[7]=0xC0;
cmd[9]=sizeof(dvd_C0);
cmd[11]=0;
if ((err=cmd.transport(READ,dvd_C0,sizeof(dvd_C0))))
{ sperror("READ DVD STRUCTURE#C0",err); return 1; }
printf ("Persistent Write Protection is %s\n",
dvd_C0[4]&0x02 ? "on" : "off");
} while (0);
return 0;
}

34
genasctable.pl Executable file
View File

@ -0,0 +1,34 @@
#!/bin/env perl
print <<___;
const char *ASC_lookup (int code)
{ static const struct { int code; const char *msg; } _table [] = {
___
while(<>)
{ chomp;
if (m/([0-9A-F\-\/]+)\s+([0-9A-F]{2})\s+([0-9A-F]{2})\s+(.*)/i)
{ printf " { 0x%s%s, \"%s\" },\n",$2,$3,$4; }
}
print <<___;
{ 0xFFFF, NULL }
};
int sz = sizeof(_table)/sizeof(_table[0])/2,i=sz;
code &= 0xFFFF;
while (sz)
{ if (_table[i].code == code) return _table[i].msg;
if (_table[i].code > code)
{ if (sz/=2) i -= sz;
else while (_table[--i].code > code);
}
else
{ if (sz/=2) i += sz;
else while (_table[++i].code < code);
}
}
return _table[i].code==code ? _table[i].msg : NULL;
}
___

228
growisofs.1 Normal file
View File

@ -0,0 +1,228 @@
.TH GROWISOFS 1m "1 Mar 2008" "growisofs 7.1"
.SH NAME
growisofs \- combined mkisofs frontend/DVD recording program.
.SH SYNOPSIS
.B growisofs
[\fB\-dry\-run\fP]
[\fB\-dvd\-compat\fP]
[\fB\-overburn\fP]
[\fB\-speed=1\fP]
\-[\fBZ|M\fP]
.I /dev/dvd
.I <mkisofs-options>
.SH DESCRIPTION
\fBgrowisofs\fP was originally designed as a frontend to \fBmkisofs\fP
to facilitate appending of data to ISO9660 volumes residing on
random-access media such as DVD+RW, DVD\-RAM, plain files, hard disk
partitions. In the course of development general purpose DVD recording
support was implemented, and as of now \fBgrowisofs\fP supports not
only random-access media, but even mastering of multisession DVD media
such as DVD+R and DVD\-R/\-RW, as well as Blu\-ray Disc. In addition
\fBgrowisofs\fP supports first-/single-session recording of
\fIarbitrary pre-mastered image\fP (formatted as UDF, ISO9660 or any
other file system, if formatted at all) to all supported DVD media
types.
.SH OPTIONS
.TP
.BI \-Z\ /dev/dvd
Burn an initial session to the selected device. A special form of this
option is recognized to support burning of pre-mastered images. See
EXAMPLES section for further details.
.TP
.BI \-M\ /dev/dvd
Merge a new session to an existing one.
.TP
.BI \-version
Print version information and invoke \fBmkisofs\fP, also with \-version
option.
.TP
.BI \-dvd\-compat
Provide maximum media compatibility with DVD\-ROM/\-Video. In write-once
DVD+R or DVD\-R context this results in unappendable recording
(closed disk). In DVD+RW context it instructs the logical unit to
explicitly burn [otherwise optional] lead\-out.
.TP
.BI \-dry\-run
At dry\-run \fBgrowisofs\fP performs all the steps till, but not
including the first write operation. Most notably check for "overburn"
condition is performed, which implies that mkisofs is invoked and
terminated prematurely.
.TP
.BI \-overburn
Normally single layer DVD media can accommodate up to approximately
4.700.000.000 bytes (in marketing speech 4.7GB). In other words a DVD
can contain about 4.377 GiB or 4482 MiB. Same kind of arithmetics
applies to Blu\-ray Disc capacity of 25.000.000.000 bytes. Anyway,
growisofs won't start without this option, if "overburn" condition
appears to be unavoidable.
.TP
.BI \-speed=N
An option to control recording velocity. Most commonly you'll use
\fB\-speed=1\fP with "no\-name" media, if default speed setting messes
up the media. Keep in mind that \fBN\fP essentially denotes speed
\fIclosest\fP to N*1385KBps in DVD or N*4496KBps in Blu\-ray Disc case
among those offered by unit for currently mounted media. The list can
be found in \fBdvd+rw\-mediainfo\fP output. Note that Blu\-ray Disc
recordings are commonly performed at ~1/2 of advertised speed, because
of defect management being in effect.
.TP
.BI <mkisofs-options>
More options can be found in the manpage for \fBmkisofs\fP.
.P
There are several undocumented options commonly denoted with
\fB\-use\-the\-force\-luke\fP prefix. Some of them serve debugging
purposes. Some require certain knowledge about recording process or
even OS kernel internals and as being such can induce confusing
behaviour. Some are to be used in very specific situations better
recognized by front-ends or automated scripts. Rationale behind leaving
these options undocumented is that those few users who would actually
need to use them directly can as well consult the source code or obtain
specific instructions elsewhere.
.SH DIFFERENCES WITH RUNNING MKISOFS DIRECTLY
.P
When using growisofs you may not use the
.B \-o
option for an output file.
.B growisofs
dumps the image directly to the media;
.P
You don't have to specify the
.B \-C
option to create a higher level session on a multisession disk,
.B growisofs
will construct one for you;
.P
Otherwise everything that applies to
.I [multisession]
mastering with
.B mkisofs
applies to
.B growisofs
as well.
.B growisofs
needs at least
.B mkisofs
version 1.14, version 2.0 is required for multisession write-once
recordings.
.SH EXAMPLES
Actual device names vary from one operating system to another. We use
\fI/dev/dvd\fP as a collective name or as symbolic link to the actual
device if you wish. Under Linux it will most likely be an ide\-scsi
device such as "/dev/scd0." Under NetBSD/OpenBSD it has to be a
\fIcharacter\fP SCSI CD\-ROM device such as "/dev/rcd0c." Under Solaris
it also has to be a \fIcharacter\fP SCSI/ATAPI CD\-ROM device, e.g.
"/dev/rdsk/c0t1d0s2" or "/vol/dev/aliases/cdrom0." And likewise in
HP\-UX, IRIX and Mac OS X...
To master and burn an ISO9660 volume with Joliet and Rock\-Ridge
extensions on a DVD or Blu\-ray Disc:
growisofs \fB\-Z\fP /dev/dvd \fB\-R \-J\fP /some/files
To append more data to same media:
growisofs \fB\-M\fP /dev/dvd \fB\-R \-J\fP /more/files
Make sure to use \fIthe same options\fP for both initial burning and
when appending data.
To finalize the multisession DVD maintaining maximum compatibility:
growisofs \fB\-M\fP /dev/dvd\fB=\fP/dev/zero
To use \fBgrowisofs\fP to write a pre-mastered ISO-image to a DVD:
growisofs \-dvd\-compat \-Z /dev/dvd\fB=\fPimage.iso
where image.iso represents an arbitrary object in the filesystem, such
as file, named pipe or device entry. Nothing is growing here and
command name is not intuitive in this context.
.SH NOTES
If executed under sudo(8) growisofs refuses to start. This is done for
the following reason. Naturally growisofs has to access the data set to
be recorded to optical media, either indirectly by letting mkisofs
generate ISO9660 layout on-the-fly or directly if a pre-mastered image
is to be recorded. Being executed under sudo(8), growisofs effectively
grants sudoers read access to \fIany\fP file in the file system. The
situation is intensified by the fact that growisofs parses MKISOFS
environment variable in order to determine alternative path to mkisofs
executable image. This means that being executed under sudo(8),
growisofs effectively grants sudoers right to execute program of their
choice with elevated privileges. If you for any reason still find the
above acceptable and are willing to take the consequences, then
consider running following wrapper script under sudo(8) in place for
real growisofs binary.
.nf
#!/bin/ksh
unset SUDO_COMMAND
export MKISOFS=/path/to/trusted/mkisofs
exec growisofs "$@"
.fi
But note that the recommended alternative to the above "workaround" is
actually to install growisofs set\-root\-uid, in which case it will drop
privileges prior accessing data or executing mkisofs in order to
preclude unauthorized access to the data.
If the media already carries isofs and \fBgrowisofs\fP is invoked with
\fB\-Z\fP option non-interactively, e.g. through cron, it shall fail
with "FATAL: /dev/dvd already carries isofs!" Note that only ISO9660 is
recognized, you can perfectly zap e.g. an UDF filesystem
non-interactively. Recommendation is to prepare media for unattended
usage by re-formatting or nullifying first 64KB in advance.
"Overburn" protection in pre-mastered image context works only with
plain files and ISO9660 formatted volumes. E.g. [given that /dev/root
is an ext2 formatted file system larger than 4.7GB] /dev/dvd=/dev/root is
bound to produce corrupted recording.
Note that DVD+RW re-formatting procedure does not substitute for
blanking. If you want to nullify the media, e.g. for privacy reasons,
do it explicitly with 'growisofs \-Z /dev/dvd\fB=/dev/zero\fP'.
Playback of re-writable DVD media, both DVD+RW and DVD\-RW, might be
limited in legacy DVD\-ROM/\-Video units. In most cases this is due
to lower reflectivity of such media.
Even though growisofs supports it, playback of multisession write-once
DVD might be limited to the first session for two reasons:
.TP
\(bu
not all DVD\-ROM players are capable of multi-border DVD\-R playback,
even less are aware of DVD+R multisessioning, burner unit therefore
might be the only one in your vicinity capable of accessing files
written at different occasions;
.TP
\(bu
OS might fail to mount multisession DVD for various reasons;
.PP
The above is not applicable to DVD+RW, DVD\-RW Restricted Overwrite,
DVD\-RAM or Blu\-ray Disc, as volumes are grown within a single session.
When growisofs "runs into" blank Blu\-ray Disc media, BD\-RE or BD\-R,
it gets pre-formatted with minimal spare area size of 256MB.
.SH SEE ALSO
Most up-to-date information on dvd+rw\-tools is available at
http://fy.chalmers.se/~appro/linux/DVD+RW/.
.PP
The manpage for \fBmkisofs\fP.
.SH AUTHORS
Andy Polyakov <appro@fy.chalmers.se> stands for programming and on-line
information.
This manpage is currently maintained by Huub Reuver
<h_reuver@mantell.xs4all.nl>.
.SH LICENSE
\fBgrowisofs\fP is distributed under GNU GPL.

3594
growisofs.c Normal file

File diff suppressed because it is too large Load Diff

2222
growisofs_mmc.cpp Normal file

File diff suppressed because it is too large Load Diff

1271
index.html Normal file

File diff suppressed because it is too large Load Diff

231
keys.txt Normal file
View File

@ -0,0 +1,231 @@
SK ASC ASCQ Description
0 00 00 NO ADDITIONAL SENSE INFORMATION
B 00 06 I/O PROCESS TERMINATED
5 00 11 AUDIO PLAY OPERATION IN PROGRESS
5 00 12 AUDIO PLAY OPERATION PAUSED
5 00 13 AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED
5 00 14 AUDIO PLAY OPERATION STOPPED DUE TO ERROR
5 00 15 NO CURRENT AUDIO STATUS TO RETURN
5 00 16 OPERATION IN PROGRESS
4 00 17 CLEANING REQUESTED
3 02 00 NO SEEK COMPLETE
2 04 00 LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE
2 04 01 LOGICAL UNIT IS IN PROCESS OF BECOMING READY
2 04 02 LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED
2 04 03 LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED
0/2 04 04 LOGICAL UNIT NOT READY, FORMAT IN PROGRESS
2 04 07 LOGICAL UNIT NOT READY, OPERATION IN PROGRESS
2 04 08 LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS
2 04 09 LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS
4 05 00 LOGICAL UNIT DOES NOT RESPOND TO SELECTION
3 06 00 NO REFERENCE POSITION FOUND
5 07 00 MULTIPLE PERIPHERAL DEVICES SELECTED
4 08 00 LOGICAL UNIT COMMUNICATION FAILURE
4 08 01 LOGICAL UNIT COMMUNICATION TIMEOUT
4 08 02 LOGICAL UNIT COMMUNICATION PARITY ERROR
4 08 03 LOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)
4 09 00 TRACK FOLLOWING ERROR
4 09 01 TRACKING SERVO FAILURE
4 09 02 FOCUS SERVO FAILURE
4 09 03 SPINDLE SERVO FAILURE
4 09 04 HEAD SELECT FAULT
6 0A 00 ERROR LOG OVERFLOW
1 0B 00 WARNING
1 0B 01 WARNING - SPECIFIED TEMPERATURE EXCEEDED
1 0B 02 WARNING - ENCLOSURE DEGRADED
1 0B 03 WARNING - BACKGROUND SELF-TEST FAILED
1 0B 04 WARNING - BACKGROUND PRE-SCAN DETECTED MEDIUM ERROR
1 0B 05 WARNING - BACKGROUND MEDIUM SCAN DETECTED MEDIUM ERROR
3 0C 00 WRITE ERROR
1 0C 01 WRITE ERROR - RECOVERED WITH AUTO-REALLOCATION
3 0C 02 WRITE ERROR - AUTO-REALLOCATION FAILED
3 0C 03 WRITE ERROR - RECOMMEND REASSIGNMENT
2/3 0C 07 WRITE ERROR - RECOVERY NEEDED
3 0C 08 WRITE ERROR - RECOVERY FAILED
3 0C 09 WRITE ERROR - LOSS OF STREAMING
3 0C 0A WRITE ERROR - PADDING BLOCKS ADDED
2 0C 0F DEFECTS IN ERROR WINDOW
3 11 00 UNRECOVERED READ ERROR
3 11 01 READ RETRIES EXHAUSTED
3 11 02 ERROR TOO LONG TO CORRECT
3 11 05 L-EC UNCORRECTABLE ERROR
3 11 06 CIRC UNRECOVERED ERROR
3 11 0F ERROR READING UPC/EAN NUMBER
3 11 10 ERROR READING ISRC NUMBER
B 11 11 READ ERROR - LOSS OF STREAMING
3/4 15 00 RANDOM POSITIONING ERROR
3/4 15 01 MECHANICAL POSITIONING ERROR
3 15 02 POSITIONING ERROR DETECTED BY READ OF MEDIUM
1 17 00 RECOVERED DATA WITH NO ERROR CORRECTION APPLIED
1 17 01 RECOVERED DATA WITH RETRIES
1 17 02 RECOVERED DATA WITH POSITIVE HEAD OFFSET
1 17 03 RECOVERED DATA WITH NEGATIVE HEAD OFFSET
1 17 04 RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED
1 17 05 RECOVERED DATA USING PREVIOUS SECTOR ID
1 17 07 RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT
1 17 08 RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE
1 17 09 RECOVERED DATA WITHOUT ECC - DATA REWRITTEN
1 18 00 RECOVERED DATA WITH ERROR CORRECTION APPLIED
1 18 01 RECOVERED DATA WITH ERROR CORR. & RETRIES APPLIED
1 18 02 RECOVERED DATA - DATA AUTO-REALLOCATED
1 18 03 RECOVERED DATA WITH CIRC
1 18 04 RECOVERED DATA WITH L-EC
1 18 05 RECOVERED DATA - RECOMMEND REASSIGNMENT
1 18 06 RECOVERED DATA - RECOMMEND REWRITE
1 18 08 RECOVERED DATA WITH LINKING
5 1A 00 PARAMETER LIST LENGTH ERROR
4 1B 00 SYNCHRONOUS DATA TRANSFER ERROR
A 1D 00 MISCOMPARE DURING VERIFY OPERATION
5 20 00 INVALID COMMAND OPERATION CODE
5 21 00 LOGICAL BLOCK ADDRESS OUT OF RANGE
5 21 01 INVALID ELEMENT ADDRESS
5 21 02 INVALID ADDRESS FOR WRITE
5 21 03 INVALID WRITE CROSSING LAYER JUMP
5 22 00 ILLEGAL FUNCTION
5 24 00 INVALID FIELD IN CDB
5 25 00 LOGICAL UNIT NOT SUPPORTED
5 26 00 INVALID FIELD IN PARAMETER LIST
5 26 01 PARAMETER NOT SUPPORTED
5 26 02 PARAMETER VALUE INVALID
5 26 03 THRESHOLD PARAMETERS NOT SUPPORTED
5 26 04 INVALID RELEASE OF PERSISTENT RESERVATION
7 27 00 WRITE PROTECTED
7 27 01 HARDWARE WRITE PROTECTED
7 27 02 LOGICAL UNIT SOFTWARE WRITE PROTECTED
7 27 03 ASSOCIATED WRITE PROTECT
7 27 04 PERSISTENT WRITE PROTECT
7 27 05 PERMANENT WRITE PROTECT
7 27 06 CONDITIONAL WRITE PROTECT
6 28 00 NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED
6 28 01 IMPORT OR EXPORT ELEMENT ACCESSED
6 28 02 FORMAT-LAYER MAY HAVE CHANGED
6 29 00 POWER ON, RESET, OR BUS DEVICE RESET OCCURRED
6 29 01 POWER ON OCCURRED
6 29 02 BUS RESET OCCURRED
6 29 03 BUS DEVICE RESET FUNCTION OCCURRED
6 29 04 DEVICE INTERNAL RESET
6 2A 00 PARAMETERS CHANGED
6 2A 01 MODE PARAMETERS CHANGED
6 2A 02 LOG PARAMETERS CHANGED
6 2A 03 RESERVATIONS PREEMPTED
5 2B 00 COPY CANNOT EXECUTE SINCE INITIATOR CANNOT DISCONNECT
5 2C 00 COMMAND SEQUENCE ERROR
5 2C 03 CURRENT PROGRAM AREA IS NOT EMPTY
5 2C 04 CURRENT PROGRAM AREA IS EMPTY
6 2E 00 INSUFFICIENT TIME FOR OPERATION
6 2F 00 COMMANDS CLEARED BY ANOTHER INITIATOR
2/5 30 00 INCOMPATIBLE MEDIUM INSTALLED
2/5 30 01 CANNOT READ MEDIUM - UNKNOWN FORMAT
2/5 30 02 CANNOT READ MEDIUM - INCOMPATIBLE FORMAT
2/5 30 03 CLEANING CARTRIDGE INSTALLED
2/5 30 04 CANNOT WRITE MEDIUM - UNKNOWN FORMAT
2/5 30 05 CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT
2/5 30 06 CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM
2/5 30 07 CLEANING FAILURE
5 30 08 CANNOT WRITE - APPLICATION CODE MISMATCH
5 30 09 CURRENT SESSION NOT FIXATED FOR APPEND
5 30 10 MEDIUM NOT FORMATTED
2/5 30 11 CANNOT WRITE MEDIUM - UNSUPPORTED MEDIUM VERSION
3 31 00 MEDIUM FORMAT CORRUPTED
3 31 01 FORMAT COMMAND FAILED
3 31 02 ZONED FORMATTING FAILED DUE TO SPARE LINKING
3 32 00 NO DEFECT SPARE LOCATION AVAILABLE
- 34 00 ENCLOSURE FAILURE
- 35 00 ENCLOSURE SERVICES FAILURE
- 35 01 UNSUPPORTED ENCLOSURE FUNCTION
- 35 02 ENCLOSURE SERVICES UNAVAILABLE
- 35 03 ENCLOSURE SERVICES TRANSFER FAILURE
- 35 04 RNCLOSURE SERVICES TRANSFER REFUSED
- 35 05 ENCLOSURE SERVICES CHECKSUM ERROR
1 37 00 ROUNDED PARAMETER
5 39 00 SAVING PARAMETERS NOT SUPPORTED
2 3A 00 MEDIUM NOT PRESENT
2 3A 01 MEDIUM NOT PRESENT - TRAY CLOSED
2 3A 02 MEDIUM NOT PRESENT - TRAY OPEN
2 3A 03 MEDIUM NOT PRESENT - LOADABLE
6 3B 0D MEDIUM DESTINATION ELEMENT FULL
6 3B 0E MEDIUM SOURCE ELEMENT EMPTY
6 3B 0F END OF MEDIUM REACHED
6 3B 11 MEDIUM MAGAZINE NOT ACCESSIBLE
6 3B 12 MEDIUM MAGAZINE REMOVED
6 3B 13 MEDIUM MAGAZINE INSERTED
6 3B 14 MEDIUM MAGAZINE LOCKED
6 3B 15 MEDIUM MAGAZINE UNLOCKED
4 3B 16 MECHANICAL POSITIONING OR CHANGER ERROR
5 3D 00 INVALID BITS IN IDENTIFY MESSAGE
2 3E 00 LOGICAL UNIT HAS NOT SELF-CONFIGURED YET
4 3E 01 LOGICAL UNIT FAILURE
4 3E 02 TIMEOUT ON LOGICAL UNIT
6 3F 00 TARGET OPERATING CONDITIONS HAVE CHANGED
6 3F 01 MICROCODE HAS BEEN CHANGED
6 3F 02 CHANGED OPERATING DEFINITION
6 3F 03 INQUIRY DATA HAS CHANGED
4 40 NN DIAGNOSTIC FAILURE ON COMPONENT NN (80H-FFH)
5 43 00 MESSAGE ERROR
4 44 00 INTERNAL TARGET FAILURE
B 45 00 SELECT OR RESELECT FAILURE
4 46 00 UNSUCCESSFUL SOFT RESET
4 47 00 SCSI PARITY ERROR
B 48 00 INITIATOR DETECTED ERROR MESSAGE RECEIVED
B 49 00 INVALID MESSAGE ERROR
4 4A 00 COMMAND PHASE ERROR
4 4B 00 DATA PHASE ERROR
4 4C 00 LOGICAL UNIT FAILED SELF-CONFIGURATION
B 4D NN TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG)
B 4E 00 OVERLAPPED COMMANDS ATTEMPTED
3 51 00 ERASE FAILURE
3 51 01 ERASE FAILURE - INCOMPLETE ERASE OPERATION DETECTED
4 53 00 MEDIA LOAD OR EJECT FAILED
5 53 02 MEDIUM REMOVAL PREVENTED
5 55 00 SYSTEM RESOURCE FAILURE
3 57 00 UNABLE TO RECOVER TABLE-OF-CONTENTS
6 5A 00 OPERATOR REQUEST OR STATE CHANGE INPUT
6 5A 01 OPERATOR MEDIUM REMOVAL REQUEST
6 5A 02 OPERATOR SELECTED WRITE PROTECT
6 5A 03 OPERATOR SELECTED WRITE PERMIT
6 5B 00 LOG EXCEPTION
6 5B 01 THRESHOLD CONDITION MET
6 5B 02 LOG COUNTER AT MAXIMUM
6 5B 03 LOG LIST CODES EXHAUSTED
1 5D 00 FAILURE PREDICTION THRESHOLD EXCEEDED
1 5D 01 MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED
1 5D 02 LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED
1 5D 03 SPARE AREA EXHAUSTION FAILURE PREDICTION THRESHOLD EXCEEDED
1 5D FF FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)
6 5E 00 LOW POWER CONDITION ON
6 5E 01 IDLE CONDITION ACTIVATED BY TIMER
6 5E 02 STANDBY CONDITION ACTIVATED BY TIMER
6 5E 03 IDLE CONDITION ACTIVATED BY COMMAND
6 5E 04 STANDBY CONDITION ACTIVATED BY COMMAND
5 63 00 END OF USER AREA ENCOUNTERED ON THIS TRACK
5 63 01 PACKET DOES NOT FIT IN AVAILABLE SPACE
5 64 00 ILLEGAL MODE FOR THIS TRACK
5 64 01 INVALID PACKET SIZE
4 65 00 VOLTAGE FAULT
5 6F 00 COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE
5 6F 01 COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT
5 6F 02 COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED
5 6F 03 READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION
5 6F 04 MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION
5 6F 05 LOGICAL UNIT REGION MUST BE PERMANENT/REGION RESET COUNT ERROR
5 6F 06 INSUFFICIENT BLOCK COUNT FOR BINDING NONCE RECORDING
5 6F 07 CONFLICT IN BINDING NONCE RECORDING
3 72 00 SESSION FIXATION ERROR
3 72 01 SESSION FIXATION ERROR WRITING LEAD-IN
3 72 02 SESSION FIXATION ERROR WRITING LEAD-OUT
5 72 03 SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION
5 72 04 EMPTY OR PARTIALLY WRITTEN RESERVED TRACK
5 72 05 NO MORE TRACK RESERVATIONS ALLOWED
5 72 06 RMZ EXTENSION IS NOT ALLOWED
5 72 07 NO MORE TEST ZONE EXTENSIONS ARE ALLOWED
3 73 00 CD CONTROL ERROR
1 73 01 POWER CALIBRATION AREA ALMOST FULL
3 73 02 POWER CALIBRATION AREA IS FULL
3 73 03 POWER CALIBRATION AREA ERROR
3 73 04 PROGRAM MEMORY AREA UPDATE FAILURE
3 73 05 PROGRAM MEMORY AREA IS FULL
1 73 06 RMA/PMA IS ALMOST FULL
3 73 10 CURRENT POWER CALIBRATION AREA IS ALMOST FULL
3 73 11 CURRENT POWER CALIBRATION AREA IS FULL
5 73 17 RDZ IS FULL
8 -- -- BLANK CHECK

84
mp.h Normal file
View File

@ -0,0 +1,84 @@
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>
#define THR_TYPE DWORD WINAPI
static void *__thread_create(DWORD (WINAPI *func)(PVOID),void *arg)
{ return (void *)CreateThread(NULL,64*1024,func,arg,0,NULL); }
static void __thread_yield(void) { (void)SwitchToThread(); }
static int __thread_wait(void *h)
{ DWORD ret;
if (WaitForSingleObject(h,INFINITE)==WAIT_OBJECT_0 &&
GetExitCodeThread(h,&ret))
{ CloseHandle(h);
return ret;
}
return -1;
}
static void *__semaphore_create(int max){ return CreateSemaphore(NULL,0,max,NULL); }
static int __semaphore_wait(void *h) { return WaitForSingleObject(h,INFINITE)!=WAIT_FAILED; }
static int __semaphore_post(void *h) { return ReleaseSemaphore(h,1,NULL); }
static void __semaphore_close(void *h) { CloseHandle(h); }
#else
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <stdlib.h>
#include <limits.h>
#define THR_TYPE int
static void *__thread_create(int (*func)(void *),void *arg)
{ pthread_t h;
pthread_attr_t attr;
size_t stack_sz=16*1024;
#ifdef PTHREAD_STACK_MIN
stack_sz += PTHREAD_STACK_MIN;
#endif
if (pthread_attr_init(&attr)==0 &&
pthread_attr_setstacksize(&attr,stack_sz)==0 &&
pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM)==0 &&
pthread_create(&h,&attr,(void *(*)(void *))func,arg)==0 )
return (void *)h;
return NULL;
}
static void __thread_yield(void) { (void)sched_yield(); }
static int __thread_wait(void *h)
{ void *ret;
if (pthread_join((pthread_t)((size_t)h),&ret)==0)
return (int)ret;
return -1;
}
#if defined(__APPLE__) && defined(__MACH__)
// Mac OS X doesn't implement unnamed semaphores, g-r-r-r-r...
static void *__semaphore_create(int max)
{ sem_t *h = sem_open ("growisofs",O_CREAT|O_EXCL,0700,0);
if (h==(sem_t*)SEM_FAILED) return NULL;
sem_unlink ("growisofs");
return h;
}
static void __semaphore_close(void *h) { sem_close(h); }
#else
static void *__semaphore_create(int max)
{ sem_t *h = calloc(1,sizeof(sem_t));
if (h==NULL) return h;
if (sem_init(h,0,0)<0) { free(h); return NULL; }
return h;
}
static void __semaphore_close(void *h) { sem_destroy(h), free(h); }
#endif
static int __semaphore_wait(void *h) { return sem_wait(h)==0; }
static int __semaphore_post(void *h) { return sem_post(h)==0; }
#endif

350
rpl8.cpp Normal file
View File

@ -0,0 +1,350 @@
#if 0
#
# The code is in public domain, May-September 2002.
#
# RICOH Program Loader 8 (primarily DVD+RW units) for Linux 2.4 and
# upwards. So far has been tested with:
# - HP dvd100i
# - Ricoh MP5120A
# - Philips DVDRW208
# - HP dvd200i
#
# This is second version adding support for Program Loader 9 and
# firmware consistency check.
#
# The program never updates Program Loader code so that you should
# always be able to downgrade your firmware in case something goes
# wrong.
#
# - make sure you have no media in drive, optionally go to single user
# mode;
# - run 'rpl8 /dev/cdrom firmware.image.bin';
# - observe the program backing up your current firmware and uploading
# new one;
# - take system down and cycle the power;
#
# There is -dump-only option which only backs up firmware. Note that
# you might have to cycle the power even after -dump-only.
#
# "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted"
# surrounded by other nasty messages logged on console is "normal."
#
/bin/sh << EOS
MODNAME=\`expr "/$0" : '\(.*[^/]\)/*$' : '.*/\(..*\)' : '\(.*\)\..*$'\`
case "`uname -s`" in
SunOS) (set -x; g++ -fno-exceptions -O -o \$MODNAME "$0" -lvolmgt) ;;
*) (set -x; g++ -fno-exceptions -O -o \$MODNAME "$0") ;;
esac
EOS
exit
#endif
#if defined(__linux)
#define _XOPEN_SOURCE 500
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <poll.h>
#include <signal.h>
#include "transport.hxx"
#define BUFFER_BLOCK (16*1024)
#define FIRMWARE_SIZE (1024*1024)
#define MAGIC_OFFSET (32*1024)
#if FIRMWARE_SIZE%BUFFER_BLOCK!=0
#error "Invalid BUFFER_BLOCK"
#endif
#if MAGIC_OFFSET%BUFFER_BLOCK!=0
#error "Invalid BUFFER_BLOCK"
#endif
int main (int argc,char *argv[])
{ int fd,in,out,off,j;
struct stat sb;
char dump[64],*meaning;
unsigned char *buffer,*firmware,sigfile[6],sigunit[6],ascq='\xFF';
struct {
unsigned char type,skip[7];
char vendor[8],ident[16],revision[4];
} inq;
Scsi_Command cmd;
unsigned char *sense=cmd.sense();
if (argc<3)
{ fprintf (stderr,"usage: %s /dev/cdrom "
"[-[dump-only]|firmware.bin]\n",argv[0]);
return 1;
}
if ((fd=open ("/dev/zero",O_RDWR)) < 0)
{ fprintf (stderr,"unable to open(\"/dev/zero\"): "), perror(NULL);
return 1;
}
buffer = (unsigned char *)mmap(NULL,BUFFER_BLOCK,PROT_READ|PROT_WRITE,
MAP_PRIVATE,fd,0);
if (buffer==MAP_FAILED)
{ fprintf (stderr,"unable to anonymously mmap %d bytes: ",BUFFER_BLOCK),
perror (NULL);
return 1;
}
close (fd);
if (!cmd.associate(argv[1]))
{ fprintf (stderr,"%s: unable to open: ",argv[1]), perror (NULL);
return 1;
}
cmd[0]=0x12; // INQUIRY
cmd[4]=sizeof(inq);
cmd[5]=0;
if (cmd.transport(READ,(unsigned char *)&inq,sizeof(inq)))
{ perror("unable to INQUIRY, examine /var/log/message");
return 1;
}
if ((inq.type&0x1F) != 5)
{ fprintf (stderr,"\"%s\" is not a CD-ROM device\n",argv[1]);
return 1;
}
cmd[0]=0x00; // TEST UNIT READY
cmd[5]=0x80;
if (!cmd.transport())
{ fprintf (stderr,"\"%s\" is ready, is media present?\n",argv[1]);
return 1;
}
if (sense[12] != 0x3A) // should reply with "NO MEDIA"
{ fprintf (stderr,"\"%s\": unexpected ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
return 1;
}
sprintf (dump,"%.8s%.16s%.4s.bin",inq.vendor,inq.ident,inq.revision);
for(j=0;dump[j];j++) if (dump[j]==' ') dump[j]='_';
in=-1, firmware=NULL;
if (argv[2][0] != '-')
{ unsigned short cksum;
int i;
if ((in=open(argv[2],O_RDONLY)) < 0)
{ fprintf (stderr,"unable to open(\"%s\"): ",argv[2]), perror (NULL);
return 1;
}
if (fstat(in,&sb) < 0)
{ fprintf (stderr,"unable to stat(\"%s\"): ",argv[2]), perror (NULL);
return 1;
}
if (sb.st_size != FIRMWARE_SIZE)
{ fprintf (stderr,"\"%s\": size is insane\n",argv[2]);
return 1;
}
firmware=(unsigned char *)mmap(NULL,FIRMWARE_SIZE,PROT_READ,
MAP_PRIVATE,in,0);
if (firmware==MAP_FAILED)
{ fprintf (stderr,"unable to mmap(\"%s\"): ",argv[2]), perror (NULL);
return 1;
}
close (in);
memcpy(sigfile,firmware+MAGIC_OFFSET+4,6);
if (memcmp(sigfile,"MMP5",4))
{ fprintf (stderr,"\"%s\": signature is insane\n",argv[2]);
return 1;
}
for (cksum=0,i=MAGIC_OFFSET;i<FIRMWARE_SIZE-2;i++)
cksum += firmware[i];
if ((cksum&0xFF) != firmware[FIRMWARE_SIZE-1] ||
(cksum>>8) != firmware[FIRMWARE_SIZE-2]
)
{ fprintf (stderr,"\"%s\" is corrupted or encrypted\n",argv[2]);
return 1;
}
}
if ((out=open(dump,O_WRONLY|O_CREAT|O_EXCL,0666)) < 0)
{ fprintf (stderr,"unable to creat(\"%s\"): ",dump), perror (NULL);
return 1;
}
cmd[0]=0xE4; // INVOKE PROGRAM LOADER
cmd[9]=(1<<6)&0x40;
if (cmd.transport())
{ fprintf (stderr,"\"%s\": unable to invoke RICOH Program Loader "
"[ASC=%02xh/ASCQ=%02xh]\n",
argv[1],sense[12],sense[13]);
return 1;
}
do { // not really a loop, just a way to get rid of goto's...
poll(NULL,0,250);
cmd[0]=0xE4; // INVOKE PROGRAM LOADER
cmd[9]=(1<<6)&0x40;
if (cmd.transport())
{ fprintf (stderr,"\"%s\"[E4]: unexpected ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
break;
}
poll(NULL,0,250);
cmd[0]=0x12; // INQUIRY
cmd[4]=sizeof(inq);
cmd[5]=0;
if (cmd.transport(READ,(unsigned char *)&inq,sizeof(inq)))
{ perror("unable to INQUIRY, examine /var/log/message");
break;
}
if (memcmp(&inq.vendor,"RICOH Program Loader 8",24) &&
memcmp(&inq.vendor,"RICOH Program Loader 9",24) )
{ fprintf (stderr,"\"%s\": unknown Program Loader "
"%.8s|%.16s|%.4s\n",
argv[1],inq.vendor,inq.ident,inq.revision);
break;
}
fprintf (stderr,"\"%s\": dumping firmware image to \"%s\" ",
argv[1],dump);
for (off=0;off<FIRMWARE_SIZE;off+=BUFFER_BLOCK)
{ cmd[0]=0xE3; // DOWNLOAD FIRMWARE PAGE
cmd[2]=(off>>24)&0xFF;
cmd[3]=(off>>16)&0xFF;
cmd[4]=(off>>8)&0xFF;
cmd[5]=(off)&0xFF;
cmd[7]=(BUFFER_BLOCK>>8)&0xFF;
cmd[8]=(BUFFER_BLOCK)&0xFF;
cmd[9]=0;
if (cmd.transport(READ,buffer,BUFFER_BLOCK))
{ fprintf (stderr,"\"%s\"[E3]: unexpected "
"ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
in=-1;
break;
}
if (write(out,buffer,BUFFER_BLOCK) != BUFFER_BLOCK)
{ fprintf (stderr,"unable to write(\"%s\"): ",dump),
perror(NULL);
in=-1;
break;
}
fprintf (stderr,".");
if (off==MAGIC_OFFSET) { memcpy(sigunit,buffer+4,6); }
}
fprintf (stderr,"\n");
if (in==-1) break; /* dump only or we failed to backup */
#if 1
if (memcmp(sigunit,sigfile,6))
{ fprintf (stderr,"\"%s\": firmware signature mismatch "
"[%.6s|%.6s]\n",
argv[1],sigunit,sigfile);
break;
}
#endif
fprintf (stderr,"\"%s\": uploading firmware image",argv[1]);
for (off=0;off<FIRMWARE_SIZE;off+=BUFFER_BLOCK)
{ cmd[0]=0xE2; // UPLOAD FIRMWARE PAGE
cmd[5]=(BUFFER_BLOCK>>16)&0xFF;
cmd[6]=(BUFFER_BLOCK>>8)&0xFF;
cmd[7]=(BUFFER_BLOCK)&0xFF;
cmd[11]=0;
if (cmd.transport(WRITE,firmware+off,BUFFER_BLOCK))
{ fprintf (stderr,"\"%s\"[E2]: unexpected "
"ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
in=-1;
break;
}
fprintf (stderr,".");
}
fprintf (stderr,"\n");
if (in==-1) break; /* failed to upload */
fprintf (stderr,"\"%s\": unlocking firmware\n",argv[1]);
cmd[0]=0xE0; // UNLOCK FIRMWARE
cmd[3]=0;
cmd[9]=0;
if (cmd.transport())
{ fprintf (stderr,"\"%s\"[E0]: unexpected "
"ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
break;
}
fprintf (stderr,"\"%s\": ¡POINT OF NO RETURN!\n",argv[1]);
poll(NULL,0,3000);
signal (SIGINT,SIG_IGN);
signal (SIGTERM,SIG_IGN);
cmd[0]=0xE1; // FIRE IT UP
// -----v----- don't update the Program Loader code
cmd[9]=(0<<6)&0x40;
if (cmd.transport())
{ fprintf (stderr,"\"%s\"[E1]: unexpected "
"ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
break;
}
while(1)
{ poll(NULL,0,250);
cmd[0]=0x00; // TEST UNIT READY
cmd[5]=0x80;
if (!cmd.transport()) continue; // never happens?
if (sense[12] == 0xF7)
{ if (ascq != sense[13])
{ switch (ascq=sense[13])
{ case 0: meaning="preparing"; break;
case 1: meaning="erasing contents"; break;
case 2: meaning="writing contents"; break;
case 3: meaning="verifying contents"; break;
default:meaning="unknown meaning"; break;
}
fprintf (stderr,"\"%s\": %s\n",argv[1],meaning);
}
}
else if (sense[12] == 0x3A) /* no media */
{ fprintf (stderr,"\"%s\": firmware upgrade succeeded:-)\n",
argv[1]),
fprintf (stderr,"\"%s\": "
"¡CYCLE THE POWER BEFORE PROCEEDING!\n",
argv[1]);
break;
}
else
{ fprintf (stderr,"\"%s\"[0]: unexpected "
"ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
in=-1;
break;
}
}
} while (0);
cmd[0]=0xE4; // TERMINATE PROGRAM LOADER
cmd[9]=(0<<6)&0x40;
if (cmd.transport())
{ fprintf (stderr,"\"%s\": unexpected ASC=%02xh/ASCQ=%02xh\n",
argv[1],sense[12],sense[13]);
return 1;
}
return in<0;
}

2094
transport.hxx Normal file

File diff suppressed because it is too large Load Diff

58
win32err.h Normal file
View File

@ -0,0 +1,58 @@
# define EINVAL ERROR_BAD_ARGUMENTS
# define ENOMEM ERROR_OUTOFMEMORY
# define EMEDIUMTYPE ERROR_MEDIA_INCOMPATIBLE
# define ENOMEDIUM ERROR_MEDIA_OFFLINE
# define ENODEV ERROR_BAD_COMMAND
# define EAGAIN ERROR_NOT_READY
# define ENOSPC ERROR_DISK_FULL
# define EIO ERROR_NOT_SUPPORTED
# define ENXIO ERROR_GEN_FAILURE
# define EBUSY ERROR_SHARING_VIOLATION
# define ENOENT ERROR_FILE_NOT_FOUND
# define ENOTDIR ERROR_NO_VOLUME_LABEL
# define EINTR ERROR_OPERATION_ABORTED
# define FATAL_START(e) (0x10000|(e))
# define FATAL_MASK 0x0FFFF
#ifdef errno
# undef errno
#endif
#ifdef __cplusplus
static class __win32_errno__ {
public:
operator int() { return GetLastError(); }
int operator=(int e) { SetLastError(e); return e; }
} win32_errno;
# define errno win32_errno
#else
# define errno (GetLastError())
#endif
#define set_errno(e) (SetLastError(e),e)
#ifdef perror
#undef perror
#endif
#define perror win32_perror
static void win32_perror (const char *str)
{ LPSTR lpMsgBuf;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0, // Default language
(LPSTR) &lpMsgBuf,
0,
NULL
);
if (str)
fprintf (stderr,"%s: %s",str,lpMsgBuf);
else
fprintf (stderr,"%s",lpMsgBuf);
LocalFree(lpMsgBuf);
}