⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 undi.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Make a real-mode UNDI API call, passing in the opcode and the * seg:off address of a pxenv_structure on the real-mode stack. * * Two versions: undi_call() will automatically report any failure * codes, undi_call_silent() will not. */int undi_call_silent ( uint16_t opcode ) {	PXENV_EXIT_t pxenv_exit = PXENV_EXIT_FAILURE;	pxenv_exit = _undi_call ( undi.pxe->EntryPointSP.segment,				  undi.pxe->EntryPointSP.offset,				  opcode,				  OFFSET( undi.pxs ),				  SEGMENT( undi.pxs ) );	/* Return 1 for success, to be consistent with other routines */	return pxenv_exit == PXENV_EXIT_SUCCESS ? 1 : 0;}int undi_call ( uint16_t opcode ) {	if ( undi_call_silent ( opcode ) ) return 1;	printf ( "UNDI API call %#hx failed with status %#hx\n",		 opcode, undi.pxs->Status );	return 0;}/************************************************************************** * High-level UNDI API call wrappers **************************************************************************//* Install the UNDI driver from a located UNDI ROM. */int undi_loader ( void ) {	pxe_t *pxe = NULL;	/* AX contains PCI bus:devfn (PCI specification) */	undi.pxs->loader.ax = ( undi.pci.bus << 8 ) | undi.pci.devfn;	/* BX and DX set to 0xffff for non-ISAPnP devices	 * (BIOS boot specification)	 */	undi.pxs->loader.bx = 0xffff;	undi.pxs->loader.dx = 0xffff;	/* ES:DI points to PnP BIOS' $PnP structure	 * (BIOS boot specification)	 */	undi.pxs->loader.es = 0xf000;	undi.pxs->loader.di = virt_to_phys ( undi.pnp_bios ) - 0xf0000;	/* Allocate space for UNDI driver's code and data segments */	undi.driver_code_size = undi.undi_rom_id->code_size;	undi.driver_code = allot_base_memory ( undi.driver_code_size );	if ( undi.driver_code == NULL ) {		printf ( "Could not allocate %d bytes for UNDI code segment\n",			 undi.driver_code_size );		return 0;	}	undi.pxs->loader.undi_cs = SEGMENT( undi.driver_code );	undi.driver_data_size = undi.undi_rom_id->data_size;	undi.driver_data = allot_base_memory ( undi.driver_data_size );	if ( undi.driver_data == NULL ) {		printf ( "Could not allocate %d bytes for UNDI code segment\n",			 undi.driver_data_size );		return 0;	}	undi.pxs->loader.undi_ds = SEGMENT( undi.driver_data );	printf ( "Installing UNDI driver code to %hx:0000, data at %hx:0000\n",		undi.pxs->loader.undi_cs, undi.pxs->loader.undi_ds );	/* Do the API call to install the loader */	if ( ! undi_call_loader () ) return 0;	pxe = VIRTUAL( undi.pxs->loader.undi_cs, undi.pxs->loader.pxe_off );	printf ( "UNDI driver created a pixie at %hx:%hx...",		 undi.pxs->loader.undi_cs, undi.pxs->loader.pxe_off );	if ( memcmp ( pxe->Signature, "!PXE", 4 ) != 0 ) {		printf ( "invalid signature\n" );		return 0;	}	if ( checksum ( pxe, sizeof(pxe_t) ) != 0 ) {		printf ( "invalid checksum\n" );		return 0;	}	printf ( "ok\n" );	undi.pxe = pxe;	pxe_dump();	return 1;}/* Start the UNDI driver. */int eb_pxenv_start_undi ( void ) {	int success = 0;	/* AX contains PCI bus:devfn (PCI specification) */	undi.pxs->start_undi.ax = ( undi.pci.bus << 8 ) | undi.pci.devfn;	/* BX and DX set to 0xffff for non-ISAPnP devices	 * (BIOS boot specification)	 */	undi.pxs->start_undi.bx = 0xffff;	undi.pxs->start_undi.dx = 0xffff;	/* ES:DI points to PnP BIOS' $PnP structure	 * (BIOS boot specification)	 */	undi.pxs->start_undi.es = 0xf000;	undi.pxs->start_undi.di = virt_to_phys ( undi.pnp_bios ) - 0xf0000;	DBG ( "PXENV_START_UNDI => AX=%hx BX=%hx DX=%hx ES:DI=%hx:%hx\n",	      undi.pxs->start_undi.ax,	      undi.pxs->start_undi.bx, undi.pxs->start_undi.dx,	      undi.pxs->start_undi.es, undi.pxs->start_undi.di );	success = undi_call ( PXENV_START_UNDI );	DBG ( "PXENV_START_UNDI <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) undi.prestarted = 1;	return success;}int eb_pxenv_undi_startup ( void )	{	int success = 0;	DBG ( "PXENV_UNDI_STARTUP => (void)\n" );	success = undi_call ( PXENV_UNDI_STARTUP );	DBG ( "PXENV_UNDI_STARTUP <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) undi.started = 1;	return success;}int eb_pxenv_undi_cleanup ( void ) {	int success = 0;	DBG ( "PXENV_UNDI_CLEANUP => (void)\n" );	success = undi_call ( PXENV_UNDI_CLEANUP );	DBG ( "PXENV_UNDI_CLEANUP <= Status=%s\n", UNDI_STATUS(undi.pxs) );	return success;}int eb_pxenv_undi_initialize ( void ) {	int success = 0;	undi.pxs->undi_initialize.ProtocolIni = 0;	memset ( &undi.pxs->undi_initialize.reserved, 0,		 sizeof ( undi.pxs->undi_initialize.reserved ) );	DBG ( "PXENV_UNDI_INITIALIZE => ProtocolIni=%x\n" );	success = undi_call ( PXENV_UNDI_INITIALIZE );	DBG ( "PXENV_UNDI_INITIALIZE <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) undi.initialized = 1;	return success;}int eb_pxenv_undi_shutdown ( void ) {	int success = 0;	DBG ( "PXENV_UNDI_SHUTDOWN => (void)\n" );	success = undi_call ( PXENV_UNDI_SHUTDOWN );	DBG ( "PXENV_UNDI_SHUTDOWN <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) {		undi.initialized = 0;		undi.started = 0;	}	return success;}int eb_pxenv_undi_open ( void ) {	int success = 0;	undi.pxs->undi_open.OpenFlag = 0;	undi.pxs->undi_open.PktFilter = FLTR_DIRECTED | FLTR_BRDCST;		/* Multicast support not yet implemented */	undi.pxs->undi_open.R_Mcast_Buf.MCastAddrCount = 0;	DBG ( "PXENV_UNDI_OPEN => OpenFlag=%hx PktFilter=%hx "	      "MCastAddrCount=%hx\n",	      undi.pxs->undi_open.OpenFlag, undi.pxs->undi_open.PktFilter,	      undi.pxs->undi_open.R_Mcast_Buf.MCastAddrCount );	success = undi_call ( PXENV_UNDI_OPEN );	DBG ( "PXENV_UNDI_OPEN <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) undi.opened = 1;	return success;	}int eb_pxenv_undi_close ( void ) {	int success = 0;	DBG ( "PXENV_UNDI_CLOSE => (void)\n" );	success = undi_call ( PXENV_UNDI_CLOSE );	DBG ( "PXENV_UNDI_CLOSE <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) undi.opened = 0;	return success;}int eb_pxenv_undi_transmit_packet ( void ) {	int success = 0;	static const uint8_t broadcast[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };	/* XMitFlag selects unicast / broadcast */	if ( memcmp ( undi.xmit_data->destaddr, broadcast,		      sizeof(broadcast) ) == 0 ) {		undi.pxs->undi_transmit.XmitFlag = XMT_BROADCAST;	} else {		undi.pxs->undi_transmit.XmitFlag = XMT_DESTADDR;	}	/* Zero reserved dwords */	undi.pxs->undi_transmit.Reserved[0] = 0;	undi.pxs->undi_transmit.Reserved[1] = 0;	/* Segment:offset pointer to DestAddr in base memory */	undi.pxs->undi_transmit.DestAddr.segment =		SEGMENT( undi.xmit_data->destaddr );	undi.pxs->undi_transmit.DestAddr.offset =		OFFSET( undi.xmit_data->destaddr );	/* Segment:offset pointer to TBD in base memory */	undi.pxs->undi_transmit.TBD.segment = SEGMENT( &undi.xmit_data->tbd );	undi.pxs->undi_transmit.TBD.offset = OFFSET( &undi.xmit_data->tbd );	/* Use only the "immediate" part of the TBD */	undi.xmit_data->tbd.DataBlkCount = 0;		DBG ( "PXENV_UNDI_TRANSMIT_PACKET => Protocol=%hx XmitFlag=%hx ...\n"	      "... DestAddr=%hx:%hx TBD=%hx:%hx ...\n",	      undi.pxs->undi_transmit.Protocol,	      undi.pxs->undi_transmit.XmitFlag,	      undi.pxs->undi_transmit.DestAddr.segment,	      undi.pxs->undi_transmit.DestAddr.offset,	      undi.pxs->undi_transmit.TBD.segment,	      undi.pxs->undi_transmit.TBD.offset );	DBG ( "... TBD { ImmedLength=%hx Xmit=%hx:%hx DataBlkCount=%hx }\n",	      undi.xmit_data->tbd.ImmedLength,	      undi.xmit_data->tbd.Xmit.segment,	      undi.xmit_data->tbd.Xmit.offset,	      undi.xmit_data->tbd.DataBlkCount );	success = undi_call ( PXENV_UNDI_TRANSMIT );	DBG ( "PXENV_UNDI_TRANSMIT_PACKET <= Status=%s\n",	      UNDI_STATUS(undi.pxs) );	return success;}int eb_pxenv_undi_set_station_address ( void ) {	/* This will spuriously fail on some cards.  Ignore failures.	 * We only ever use it to set the MAC address to the card's	 * permanent value anyway, so it's a useless call (although we	 * make it because PXE spec says we should).	 */	DBG ( "PXENV_UNDI_SET_STATION_ADDRESS => "	      "StationAddress=%!\n",	      undi.pxs->undi_set_station_address.StationAddress );	undi_call_silent ( PXENV_UNDI_SET_STATION_ADDRESS );	DBG ( "PXENV_UNDI_SET_STATION_ADDRESS <= Status=%s\n",	      UNDI_STATUS(undi.pxs) );	return 1;}int eb_pxenv_undi_get_information ( void ) {	int success = 0;	memset ( undi.pxs, 0, sizeof ( undi.pxs ) );	DBG ( "PXENV_UNDI_GET_INFORMATION => (void)\n" );	success = undi_call ( PXENV_UNDI_GET_INFORMATION );	DBG ( "PXENV_UNDI_GET_INFORMATION <= Status=%s "	      "BaseIO=%hx IntNumber=%hx ...\n"	      "... MaxTranUnit=%hx HwType=%hx HwAddrlen=%hx ...\n"	      "... CurrentNodeAddress=%! PermNodeAddress=%! ...\n"	      "... ROMAddress=%hx RxBufCt=%hx TxBufCt=%hx\n",	      UNDI_STATUS(undi.pxs),	      undi.pxs->undi_get_information.BaseIo,	      undi.pxs->undi_get_information.IntNumber,	      undi.pxs->undi_get_information.MaxTranUnit,	      undi.pxs->undi_get_information.HwType,	      undi.pxs->undi_get_information.HwAddrLen,	      undi.pxs->undi_get_information.CurrentNodeAddress,	      undi.pxs->undi_get_information.PermNodeAddress,	      undi.pxs->undi_get_information.ROMAddress,	      undi.pxs->undi_get_information.RxBufCt,	      undi.pxs->undi_get_information.TxBufCt );	return success;}int eb_pxenv_undi_get_iface_info ( void ) {	int success = 0;	DBG ( "PXENV_UNDI_GET_IFACE_INFO => (void)\n" );	success = undi_call ( PXENV_UNDI_GET_IFACE_INFO );	DBG ( "PXENV_UNDI_GET_IFACE_INFO <= Status=%s IfaceType=%s ...\n"	      "... LinkSpeed=%x ServiceFlags=%x\n",	      UNDI_STATUS(undi.pxs),	      undi.pxs->undi_get_iface_info.IfaceType,	      undi.pxs->undi_get_iface_info.LinkSpeed,	      undi.pxs->undi_get_iface_info.ServiceFlags );	return success;}int eb_pxenv_undi_isr ( void ) {	int success = 0;	DBG ( "PXENV_UNDI_ISR => FuncFlag=%hx\n",	      undi.pxs->undi_isr.FuncFlag );		success = undi_call ( PXENV_UNDI_ISR );	DBG ( "PXENV_UNDI_ISR <= Status=%s FuncFlag=%hx BufferLength=%hx ...\n"	      "... FrameLength=%hx FrameHeaderLength=%hx Frame=%hx:%hx "	      "ProtType=%hhx ...\n... PktType=%hhx\n",	      UNDI_STATUS(undi.pxs), undi.pxs->undi_isr.FuncFlag,	      undi.pxs->undi_isr.BufferLength,	      undi.pxs->undi_isr.FrameLength,	      undi.pxs->undi_isr.FrameHeaderLength,	      undi.pxs->undi_isr.Frame.segment,	      undi.pxs->undi_isr.Frame.offset,	      undi.pxs->undi_isr.ProtType,	      undi.pxs->undi_isr.PktType );	return success;}int eb_pxenv_stop_undi ( void ) {	int success = 0;	DBG ( "PXENV_STOP_UNDI => (void)\n" );	success = undi_call ( PXENV_STOP_UNDI );	DBG ( "PXENV_STOP_UNDI <= Status=%s\n", UNDI_STATUS(undi.pxs) );	if ( success ) undi.prestarted = 0;	return success;}int eb_pxenv_unload_stack ( void ) {	int success = 0;	memset ( undi.pxs, 0, sizeof ( undi.pxs ) );	DBG ( "PXENV_UNLOAD_STACK => (void)\n" );	success = undi_call_silent ( PXENV_UNLOAD_STACK );	DBG ( "PXENV_UNLOAD_STACK <= Status=%s ...\n... (%s)\n",	      UNDI_STATUS(undi.pxs),	      ( undi.pxs->Status == PXENV_STATUS_SUCCESS ?		"base-code is ready to be removed" :		( undi.pxs->Status == PXENV_STATUS_FAILURE ?		  "the size of free base memory has been changed" :		  ( undi.pxs->Status == PXENV_STATUS_KEEP_ALL ?		    "the NIC interrupt vector has been changed" :		    "UNEXPECTED STATUS CODE" ) ) ) );	return success;}int eb_pxenv_stop_base ( void ) {	int success = 0;	DBG ( "PXENV_STOP_BASE => (void)\n" );	success = undi_call ( PXENV_STOP_BASE );	DBG ( "PXENV_STOP_BASE <= Status=%s\n", UNDI_STATUS(undi.pxs) );	return success;}/* Unload UNDI base code (if any present) and free memory. */int undi_unload_base_code ( void ) {	void *bc_code = VIRTUAL( undi.pxe->BC_Code.Seg_Addr, 0 );	size_t bc_code_size = undi.pxe->BC_Code.Seg_Size;	void *bc_data = VIRTUAL( undi.pxe->BC_Data.Seg_Addr, 0 );	size_t bc_data_size = undi.pxe->BC_Data.Seg_Size;	void *bc_stck = VIRTUAL( undi.pxe->Stack.Seg_Addr, 0 );	size_t bc_stck_size = undi.pxe->Stack.Seg_Size;	firing_squad_lineup_t lineup;	/* Don't unload if there is no base code present */	if ( undi.pxe->BC_Code.Seg_Addr == 0 ) return 1;	/* Since we never start the base code, the only time we should	 * reach this is if we were loaded via PXE.  There are many	 * different and conflicting versions of the "correct" way to	 * unload the PXE base code, several of which appear within	 * the PXE specification itself.  This one seems to work for	 * our purposes.	 */	eb_pxenv_stop_base();	eb_pxenv_unload_stack();	if ( ( undi.pxs->unload_stack.Status != PXENV_STATUS_SUCCESS ) &&	     ( undi.pxs->unload_stack.Status != PXENV_STATUS_FAILURE ) ) {		printf ( "Could not free memory allocated to PXE base code: "			 "possible memory leak\n" );		return 0;	}	/* Free data structures.  Forget what the PXE specification	 * says about how to calculate the new size of base memory;	 * basemem.c takes care of all that for us.  Note that we also	 * have to free the stack (even though PXE spec doesn't say	 * anything about it) because nothing else is going to do so.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -