|  | @@ -17,8 +17,11 @@
 | 
		
	
		
			
			| 17 | 17 |   */
 | 
		
	
		
			
			| 18 | 18 |  
 | 
		
	
		
			
			| 19 | 19 |  #include <stdio.h>
 | 
		
	
		
			
			|  | 20 | +#include <errno.h>
 | 
		
	
		
			
			|  | 21 | +#include <assert.h>
 | 
		
	
		
			
			| 20 | 22 |  #include <getopt.h>
 | 
		
	
		
			
			| 21 | 23 |  #include <ipxe/command.h>
 | 
		
	
		
			
			|  | 24 | +#include <ipxe/parseopt.h>
 | 
		
	
		
			
			| 22 | 25 |  #include <ipxe/gdbstub.h>
 | 
		
	
		
			
			| 23 | 26 |  
 | 
		
	
		
			
			| 24 | 27 |  /** @file
 | 
		
	
	
		
			
			|  | @@ -28,71 +31,76 @@
 | 
		
	
		
			
			| 28 | 31 |   */
 | 
		
	
		
			
			| 29 | 32 |  
 | 
		
	
		
			
			| 30 | 33 |  /**
 | 
		
	
		
			
			| 31 |  | - * "gdbstub" command syntax message
 | 
		
	
		
			
			|  | 34 | + * Parse GDB transport name
 | 
		
	
		
			
			| 32 | 35 |   *
 | 
		
	
		
			
			| 33 |  | - * @v argv		Argument list
 | 
		
	
		
			
			|  | 36 | + * @v text		Text
 | 
		
	
		
			
			|  | 37 | + * @ret trans		GDB transport
 | 
		
	
		
			
			|  | 38 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 34 | 39 |   */
 | 
		
	
		
			
			| 35 |  | -static void gdbstub_syntax ( char **argv ) {
 | 
		
	
		
			
			| 36 |  | -	printf ( "Usage:\n"
 | 
		
	
		
			
			| 37 |  | -		 "  %s <transport> [<options>...]\n"
 | 
		
	
		
			
			| 38 |  | -		 "\n"
 | 
		
	
		
			
			| 39 |  | -		 "Start remote debugging using one of the following transports:\n"
 | 
		
	
		
			
			| 40 |  | -		 "  serial           use serial port (if compiled in)\n"
 | 
		
	
		
			
			| 41 |  | -		 "  udp <interface>  use UDP over network interface (if compiled in)\n",
 | 
		
	
		
			
			| 42 |  | -		 argv[0] );
 | 
		
	
		
			
			|  | 40 | +static int parse_gdb_transport ( const char *text,
 | 
		
	
		
			
			|  | 41 | +				 struct gdb_transport **trans ) {
 | 
		
	
		
			
			|  | 42 | +
 | 
		
	
		
			
			|  | 43 | +	/* Sanity check */
 | 
		
	
		
			
			|  | 44 | +	assert ( text != NULL );
 | 
		
	
		
			
			|  | 45 | +
 | 
		
	
		
			
			|  | 46 | +	/* Find transport */
 | 
		
	
		
			
			|  | 47 | +	*trans = find_gdb_transport ( text );
 | 
		
	
		
			
			|  | 48 | +	if ( ! *trans ) {
 | 
		
	
		
			
			|  | 49 | +		printf ( "\"%s\": no such transport (is it compiled in?)\n",
 | 
		
	
		
			
			|  | 50 | +			 text );
 | 
		
	
		
			
			|  | 51 | +		return -ENOTSUP;
 | 
		
	
		
			
			|  | 52 | +	}
 | 
		
	
		
			
			|  | 53 | +
 | 
		
	
		
			
			|  | 54 | +	return 0;
 | 
		
	
		
			
			| 43 | 55 |  }
 | 
		
	
		
			
			| 44 | 56 |  
 | 
		
	
		
			
			|  | 57 | +/** "gdbstub" options */
 | 
		
	
		
			
			|  | 58 | +struct gdbstub_options {};
 | 
		
	
		
			
			|  | 59 | +
 | 
		
	
		
			
			|  | 60 | +/** "gdbstub" option list */
 | 
		
	
		
			
			|  | 61 | +static struct option_descriptor gdbstub_opts[] = {};
 | 
		
	
		
			
			|  | 62 | +
 | 
		
	
		
			
			|  | 63 | +/** "gdbstub" command descriptor */
 | 
		
	
		
			
			|  | 64 | +static struct command_descriptor gdbstub_cmd =
 | 
		
	
		
			
			|  | 65 | +	COMMAND_DESC ( struct gdbstub_options, gdbstub_opts, 1, MAX_ARGUMENTS,
 | 
		
	
		
			
			|  | 66 | +		       "<transport> [<options>...]",
 | 
		
	
		
			
			|  | 67 | +		       "Start remote debugging using one of the following "
 | 
		
	
		
			
			|  | 68 | +		       "transports:\n"
 | 
		
	
		
			
			|  | 69 | +		       "  serial           use serial port (if compiled in)\n"
 | 
		
	
		
			
			|  | 70 | +		       "  udp <interface>  use UDP over network interface "
 | 
		
	
		
			
			|  | 71 | +		       "(if compiled in)" );
 | 
		
	
		
			
			|  | 72 | +
 | 
		
	
		
			
			| 45 | 73 |  /**
 | 
		
	
		
			
			| 46 | 74 |   * The "gdbstub" command
 | 
		
	
		
			
			| 47 | 75 |   *
 | 
		
	
		
			
			| 48 | 76 |   * @v argc		Argument count
 | 
		
	
		
			
			| 49 | 77 |   * @v argv		Argument list
 | 
		
	
		
			
			| 50 |  | - * @ret rc		Exit code
 | 
		
	
		
			
			|  | 78 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 51 | 79 |   */
 | 
		
	
		
			
			| 52 | 80 |  static int gdbstub_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 53 |  | -	static struct option longopts[] = {
 | 
		
	
		
			
			| 54 |  | -		{ "help", 0, NULL, 'h' },
 | 
		
	
		
			
			| 55 |  | -		{ NULL, 0, NULL, 0 },
 | 
		
	
		
			
			| 56 |  | -	};
 | 
		
	
		
			
			| 57 |  | -	const char *trans_name;
 | 
		
	
		
			
			|  | 81 | +	struct gdbstub_options opts;
 | 
		
	
		
			
			| 58 | 82 |  	struct gdb_transport *trans;
 | 
		
	
		
			
			| 59 |  | -	int c;
 | 
		
	
		
			
			|  | 83 | +	int rc;
 | 
		
	
		
			
			| 60 | 84 |  
 | 
		
	
		
			
			| 61 | 85 |  	/* Parse options */
 | 
		
	
		
			
			| 62 |  | -	while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
 | 
		
	
		
			
			| 63 |  | -		switch ( c ) {
 | 
		
	
		
			
			| 64 |  | -		case 'h':
 | 
		
	
		
			
			| 65 |  | -			/* Display help text */
 | 
		
	
		
			
			| 66 |  | -		default:
 | 
		
	
		
			
			| 67 |  | -			/* Unrecognised/invalid option */
 | 
		
	
		
			
			| 68 |  | -			gdbstub_syntax ( argv );
 | 
		
	
		
			
			| 69 |  | -			return 1;
 | 
		
	
		
			
			| 70 |  | -		}
 | 
		
	
		
			
			| 71 |  | -	}
 | 
		
	
		
			
			| 72 |  | -
 | 
		
	
		
			
			| 73 |  | -	/* At least one argument */
 | 
		
	
		
			
			| 74 |  | -	if ( optind == argc ) {
 | 
		
	
		
			
			| 75 |  | -		gdbstub_syntax ( argv );
 | 
		
	
		
			
			| 76 |  | -		return 1;
 | 
		
	
		
			
			| 77 |  | -	}
 | 
		
	
		
			
			|  | 86 | +	if ( ( rc = parse_options ( argc, argv, &gdbstub_cmd, &opts ) ) != 0 )
 | 
		
	
		
			
			|  | 87 | +		return rc;
 | 
		
	
		
			
			| 78 | 88 |  
 | 
		
	
		
			
			| 79 |  | -	trans_name = argv[optind++];
 | 
		
	
		
			
			|  | 89 | +	/* Parse transport name */
 | 
		
	
		
			
			|  | 90 | +	if ( ( rc = parse_gdb_transport ( argv[optind++], &trans ) ) != 0 )
 | 
		
	
		
			
			|  | 91 | +		return rc;
 | 
		
	
		
			
			| 80 | 92 |  
 | 
		
	
		
			
			| 81 | 93 |  	/* Initialise transport */
 | 
		
	
		
			
			| 82 |  | -	trans = find_gdb_transport ( trans_name );
 | 
		
	
		
			
			| 83 |  | -	if ( !trans ) {
 | 
		
	
		
			
			| 84 |  | -		printf ( "%s: no such transport (is it compiled in?)\n", trans_name );
 | 
		
	
		
			
			| 85 |  | -		return 1;
 | 
		
	
		
			
			| 86 |  | -	}
 | 
		
	
		
			
			| 87 |  | -
 | 
		
	
		
			
			| 88 | 94 |  	if ( trans->init ) {
 | 
		
	
		
			
			| 89 |  | -		if ( trans->init ( argc - optind, &argv[optind] ) != 0 ) {
 | 
		
	
		
			
			| 90 |  | -			return 1;
 | 
		
	
		
			
			|  | 95 | +		if ( ( rc = trans->init ( argc - optind,
 | 
		
	
		
			
			|  | 96 | +					  &argv[optind] ) ) != 0 ) {
 | 
		
	
		
			
			|  | 97 | +			return rc;
 | 
		
	
		
			
			| 91 | 98 |  		}
 | 
		
	
		
			
			| 92 | 99 |  	}
 | 
		
	
		
			
			| 93 | 100 |  
 | 
		
	
		
			
			| 94 | 101 |  	/* Enter GDB stub */
 | 
		
	
		
			
			| 95 | 102 |  	gdbstub_start ( trans );
 | 
		
	
		
			
			|  | 103 | +
 | 
		
	
		
			
			| 96 | 104 |  	return 0;
 | 
		
	
		
			
			| 97 | 105 |  }
 | 
		
	
		
			
			| 98 | 106 |  
 |