2 * $Id: a2boot.c,v 1.2 2003-01-15 06:24:28 jmarcus Exp $
3 * Apple II boot support code. with aid of Steven N. Hirsch
5 * based on timelord 1.6 so below copyrights still apply
7 * Copyright (c) 1990,1992 Regents of The University of Michigan.
8 * All Rights Reserved. See COPYRIGHT.
10 * The "timelord protocol" was reverse engineered from Timelord,
11 * distributed with CAP, Copyright (c) 1990, The University of
12 * Melbourne. The following copyright, supplied by The University
13 * of Melbourne, may apply to this code:
15 * This version of timelord.c is based on code distributed
16 * by the University of Melbourne as part of the CAP package.
18 * The tardis/Timelord package for Macintosh/CAP is
19 * Copyright (c) 1990, The University of Melbourne.
24 #endif /* HAVE_CONFIG_H */
26 #include <sys/param.h>
27 #include <sys/types.h>
33 #include <netatalk/at.h>
34 #include <netatalk/endian.h>
35 #include <atalk/atp.h>
36 #include <atalk/nbp.h>
40 #endif /* HAVE_SGTTY_H */
44 #include <atalk/logger.h>
50 #endif /* HAVE_NETDB_H */
54 #endif /* HAVE_FCNTL_H */
55 #ifdef HAVE_SYS_FCNTL_H
56 #include <sys/fcntl.h>
57 #endif /* HAVE_SYS_FCNTL_H */
61 #endif /* HAVE_TERMIOS_H */
62 #ifdef HAVE_SYS_TERMIOS_H
63 #include <sys/termios.h>
64 #endif /* HAVE_SYS_TERMIOS_H */
70 char *bad = "Bad request!";
75 long a2bootreq(char *fname);
81 if (( s = rindex( p, '/' )) == NULL ) {
86 fprintf( stderr, "Usage:\t%s -d -n nbpname\n", s );
91 * Unregister ourself on signal.
97 regerr = nbp_unrgstr( server, "Apple //gs", "*", NULL );
98 regerr += nbp_unrgstr( server, "Apple //e Boot", "*", NULL );
99 regerr += nbp_unrgstr( server, "ProDOS16 Image", "*", NULL );
101 LOG(log_error, logtype_default, "Can't unregister Apple II boot files %s", server );
104 LOG(log_info, logtype_default, "going down" );
108 int main( int ac, char **av )
111 struct sockaddr_at sat;
112 struct atp_block atpb;
114 char hostname[ MAXHOSTNAMELEN ];
123 if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
124 perror( "gethostname" );
127 if (( server = index( hostname, '.' )) != 0 ) {
132 while (( c = getopt( ac, av, "dn:" )) != EOF ) {
141 fprintf( stderr, "Unknown option -- '%c'\n", c );
147 * Disassociate from controlling tty.
154 dt = getdtablesize();
155 for ( i = 0; i < dt; i++ ) {
158 if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) {
159 (void)ioctl( i, TIOCNOTTY, 0 );
160 setpgid( 0, getpid());
172 if (( p = rindex( *av, '/' )) == NULL ) {
179 openlog( p, LOG_PID );
182 syslog_setup(log_debug, logtype_default, logoption_ndelay|logoption_pid, logfacility_daemon );
185 /* allocate memory */
186 memset (&sat.sat_addr, 0, sizeof (sat.sat_addr));
189 force port 3 as the semi-official ATP access port MJ 2002
191 if (( atp = atp_open( (u_int8_t)3, &sat.sat_addr )) == NULL ) {
192 LOG(log_error, logtype_default, "main: atp_open: %s", strerror( errno ) );
196 regerr = nbp_rgstr( atp_sockaddr( atp ), server, "Apple //gs", "*" );
197 regerr += nbp_rgstr( atp_sockaddr( atp ), server, "Apple //e Boot", "*" );
198 regerr += nbp_rgstr( atp_sockaddr( atp ), server, "ProDOS16 Image", "*" );
200 LOG(log_error, logtype_default, "Can't register Apple II boot files %s", server );
204 LOG(log_info, logtype_default, "%s:Apple 2 Boot started", server );
206 signal(SIGHUP, goaway);
207 signal(SIGTERM, goaway);
211 * Something seriously wrong with atp, since these assigns must
214 atpb.atp_saddr = &sat;
215 atpb.atp_rreqdata = buf;
216 bzero( &sat, sizeof( struct sockaddr_at ));
217 atpb.atp_rreqdlen = sizeof( buf );
219 if ( atp_rreq( atp, &atpb ) < 0 ) {
220 LOG(log_error, logtype_default, "main: atp_rreq: %s", strerror( errno ) );
225 bcopy( p, &req, sizeof( int32_t ));
227 p += sizeof( int32_t );
230 LOG(log_info, logtype_default, "req = %08lx",(long)req );
232 /* Byte-swap and multiply by 0x200. Converts block number to
234 fileoff = (( req & 0x00ff0000 ) >> 7 ) | (( req & 0x0000ff00 ) << 9 );
238 LOG(log_info, logtype_default, " reqblklo = %02x",(int)reqblklo );
239 LOG(log_info, logtype_default, " reqblkhi = %02x",(int)reqblkhi );
240 LOG(log_info, logtype_default, " req now = %08lx",(long)req );
244 case 0x01000000 : /* Apple IIgs both ROM 1 and ROM 3 */
245 /* LOG(log_info, logtype_default, " Req ProDOS16 Boot Blocks" ); */
246 resp = a2bootreq(_PATH_A_GS_BLOCKS);
249 case 0x02000000 : /* Apple 2 Workstation card */
250 /* LOG(log_info, logtype_default, " Req Apple //e Boot" ); */
251 resp = a2bootreq(_PATH_A_2E_BLOCKS);
254 case 0x03000000 : /* Apple IIgs both ROM 1 and ROM 3 */
255 /* LOG(log_info, logtype_default, " Req ProDOS16 Image" ); */
256 resp = a2bootreq(_PATH_P16_IMAGE);
260 LOG(log_error, logtype_default, bad );
263 *( buf + sizeof( int32_t ) ) = (unsigned char)strlen( bad );
264 strcpy( buf + 1 + sizeof( int32_t ), bad );
269 bcopy( &resp, buf, sizeof( int32_t ));
271 iov.iov_len = sizeof( int32_t ) + 512;
273 atpb.atp_sresiov = &iov;
274 atpb.atp_sresiovcnt = 1;
276 if ( atp_sresp( atp, &atpb ) < 0 ) {
277 LOG(log_error, logtype_default, "main: atp_sresp: %s", strerror( errno ) );
284 /* below MJ 2002 (initially borrowed from aep_packet */
285 long a2bootreq(fname)
291 LOG(log_info, logtype_default, " a2bootreq( %s )",fname );
293 f=open(fname,O_RDONLY );
295 LOG(log_error, logtype_default, "a2boot open error on %s",fname);
300 LOG(log_info, logtype_default, "would lseek to %08lx",fileoff);
303 readlen=read(f, buf + sizeof( int32_t ), 512 );
306 LOG(log_info, logtype_default, "length is %08lx", readlen);
309 if(readlen < 0x200) {
310 /* LOG(log_info, logtype_default, "Read to EOF"); */