• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/contrib/a2boot/
1/*
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
4 *
5 * based on timelord 1.6 so below copyrights still apply
6 *
7 * Copyright (c) 1990,1992 Regents of The University of Michigan.
8 * All Rights Reserved. See COPYRIGHT.
9 *
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:
14 *
15 *	This version of timelord.c is based on code distributed
16 *	by the University of Melbourne as part of the CAP package.
17 *
18 *	The tardis/Timelord package for Macintosh/CAP is
19 *	Copyright (c) 1990, The University of Melbourne.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif /* HAVE_CONFIG_H */
25
26#include <sys/param.h>
27#include <sys/types.h>
28#include <sys/file.h>
29#include <sys/uio.h>
30
31#include <unistd.h>
32
33#include <netatalk/at.h>
34#include <netatalk/endian.h>
35#include <atalk/atp.h>
36#include <atalk/nbp.h>
37
38#ifdef HAVE_SGTTY_H
39#include <sgtty.h>
40#endif /* HAVE_SGTTY_H */
41
42#include <errno.h>
43#include <signal.h>
44#include <atalk/logger.h>
45#include <stdio.h>
46#include <string.h>
47
48#ifdef HAVE_NETDB_H
49#include <netdb.h>
50#endif /* HAVE_NETDB_H */
51
52#ifdef HAVE_FCNTL_H
53#include <fcntl.h>
54#endif /* HAVE_FCNTL_H */
55#ifdef HAVE_SYS_FCNTL_H
56#include <sys/fcntl.h>
57#endif /* HAVE_SYS_FCNTL_H */
58
59#ifdef HAVE_TERMIOS_H
60#include <termios.h>
61#endif /* HAVE_TERMIOS_H */
62#ifdef HAVE_SYS_TERMIOS_H
63#include <sys/termios.h>
64#endif /* HAVE_SYS_TERMIOS_H */
65
66#define	TL_OK		'\0'
67#define TL_EOF		'\1'
68
69int	debug = 0;
70char	*bad = "Bad request!";
71char	buf[ 4624 ];
72char	*server;
73int32_t fileoff;
74
75long a2bootreq(char *fname);
76
77void usage( char *p )
78{
79    char	*s;
80
81    if (( s = rindex( p, '/' )) == NULL ) {
82	s = p;
83    } else {
84	s++;
85    }
86    fprintf( stderr, "Usage:\t%s -d -n nbpname\n", s );
87    exit( 1 );
88}
89
90/*
91 * Unregister ourself on signal.
92 */
93void
94goaway(int signal)
95{
96    int regerr;
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 );
100    if ( regerr < 0 ) {
101	LOG(log_error, logtype_default, "Can't unregister Apple II boot files %s", server );
102	exit( 1 );
103    }
104    LOG(log_info, logtype_default, "going down" );
105    exit( 0 );
106}
107
108int main( int ac, char **av )
109{
110    ATP		atp;
111    struct sockaddr_at	sat;
112    struct atp_block	atpb;
113    struct iovec	iov;
114    char	hostname[ MAXHOSTNAMELEN ];
115    char	*p;
116    int		c;
117    int32_t	req, resp;
118    int 	regerr;
119    extern char	*optarg;
120    extern int		optind;
121
122
123    if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
124	perror( "gethostname" );
125	exit( 1 );
126    }
127    if (( server = index( hostname, '.' )) != 0 ) {
128	*server = '\0';
129    }
130    server = hostname;
131
132    while (( c = getopt( ac, av, "dn:" )) != EOF ) {
133	switch ( c ) {
134	case 'd' :
135	    debug++;
136	    break;
137	case 'n' :
138	    server = optarg;
139	    break;
140	default :
141	    fprintf( stderr, "Unknown option -- '%c'\n", c );
142	    usage( *av );
143	}
144    }
145
146    /*
147     * Disassociate from controlling tty.
148     */
149    if ( !debug ) {
150	int		i, dt;
151
152	switch ( fork()) {
153	case 0 :
154	    dt = getdtablesize();
155	    for ( i = 0; i < dt; i++ ) {
156		(void)close( i );
157	    }
158	    if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) {
159		(void)ioctl( i, TIOCNOTTY, 0 );
160		setpgid( 0, getpid());
161		(void)close( i );
162	    }
163	    break;
164	case -1 :
165	    perror( "fork" );
166	    exit( 1 );
167	default :
168	    exit( 0 );
169	}
170    }
171
172    if (( p = rindex( *av, '/' )) == NULL ) {
173	p = *av;
174    } else {
175	p++;
176    }
177
178#ifdef ultrix
179    openlog( p, LOG_PID );
180#else /* ultrix */
181    set_processname(p);
182    syslog_setup(log_debug, logtype_default, logoption_ndelay|logoption_pid, logfacility_daemon );
183#endif /* ultrix */
184
185    /* allocate memory */
186    memset (&sat.sat_addr, 0, sizeof (sat.sat_addr));
187
188/*
189	force port 3 as the semi-official ATP access port        MJ 2002
190*/
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 ) );
193	exit( 1 );
194    }
195
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", "*" );
199    if ( regerr < 0 ) {
200	LOG(log_error, logtype_default, "Can't register Apple II boot files %s", server );
201	exit( 1 );
202    }
203
204    LOG(log_info, logtype_default, "%s:Apple 2 Boot started", server );
205
206	signal(SIGHUP, goaway);
207	signal(SIGTERM, goaway);
208
209    for (;;) {
210	/*
211	 * Something seriously wrong with atp, since these assigns must
212	 * be in the loop...
213	 */
214	atpb.atp_saddr = &sat;
215	atpb.atp_rreqdata = buf;
216	bzero( &sat, sizeof( struct sockaddr_at ));
217	atpb.atp_rreqdlen = sizeof( buf );
218
219	if ( atp_rreq( atp, &atpb ) < 0 ) {
220	LOG(log_error, logtype_default, "main: atp_rreq: %s", strerror( errno ) );
221	    exit( 1 );
222	}
223
224	p = buf;
225	bcopy( p, &req, sizeof( int32_t ));
226	req = ntohl( req );
227	p += sizeof( int32_t );
228
229/*
230    LOG(log_info, logtype_default, "req = %08lx",(long)req );
231*/
232	/* Byte-swap and multiply by 0x200. Converts block number to
233	   file offset. */
234	fileoff = (( req & 0x00ff0000 ) >> 7 ) | (( req & 0x0000ff00 ) << 9 );
235	req &= 0xff000000;
236
237/*
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 );
241*/
242
243	switch( 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);
247	    break;
248
249	case 0x02000000 :	/* Apple 2 Workstation card  */
250/*    LOG(log_info, logtype_default, "          Req Apple //e Boot" );  */
251	    	resp = a2bootreq(_PATH_A_2E_BLOCKS);
252	    break;
253
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);
257	    break;
258
259	default :
260	    LOG(log_error, logtype_default, bad );
261
262	    resp = TL_EOF;
263	    *( buf + sizeof( int32_t ) ) = (unsigned char)strlen( bad );
264	    strcpy( buf + 1 + sizeof( int32_t ), bad );
265
266	    break;
267	}
268
269	bcopy( &resp, buf, sizeof( int32_t ));
270
271	iov.iov_len = sizeof( int32_t ) + 512;
272	iov.iov_base = buf;
273	atpb.atp_sresiov = &iov;
274	atpb.atp_sresiovcnt = 1;
275
276	if ( atp_sresp( atp, &atpb ) < 0 ) {
277	    LOG(log_error, logtype_default, "main: atp_sresp: %s", strerror( errno ) );
278	    exit( 1 );
279	}
280    }
281}
282
283
284/* below MJ 2002 (initially borrowed from aep_packet */
285long a2bootreq(fname)
286	char	*fname;
287{
288	int f,m;
289	int32_t readlen;
290/*
291    LOG(log_info, logtype_default, "          a2bootreq( %s )",fname );
292*/
293	f=open(fname,O_RDONLY );
294	if(f==EOF) {
295	LOG(log_error, logtype_default, "a2boot open error on %s",fname);
296		return close(f);
297	}
298
299/*
300    LOG(log_info, logtype_default, "would lseek to %08lx",fileoff);
301*/
302	lseek(f,fileoff,0);
303	readlen=read(f, buf + sizeof( int32_t ), 512 );
304
305/*
306    LOG(log_info, logtype_default, "length is %08lx", readlen);
307*/
308
309	if(readlen < 0x200) {
310/*    LOG(log_info, logtype_default, "Read to EOF");  */
311		close(f);
312		return TL_EOF;
313	}
314	close(f);
315	return  TL_OK;
316}
317
318