/*
 * DF-3762 trigger — logic replication of the unchecked-PHY-read defect in
 * sys/dev/netif/ig_hal/e1000_phy.c:e1000_link_stall_workaround_hv() (line 3848).
 *
 * The real function does:
 *
 *     u16 data;                                          // uninit (line 3840)
 *     hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);      // return IGNORED (3848)
 *     if (data & PHY_CONTROL_LB)                         // uninit read (3849)
 *             return E1000_SUCCESS;
 *
 * When read_reg fails (e1000_read_phy_reg_hv -> e1000_read_phy_reg_mdic
 * MDIC timeout/error: -E1000_ERR_PHY), it returns WITHOUT writing *data.
 * The caller then branches on uninitialized kernel stack.
 *
 * This harness replicates the exact call/decision structure with an
 * instrumented shim so the defect is provable on any machine, no e1000
 * hardware needed (the guest is virtio-only: no em/emx/igb NIC present,
 * so the in-kernel path cannot be executed there).
 *
 * Build: cc -O2 -o trigger trigger.c
 * Run:   ./trigger
 * Success criterion: prints "decision on UNINITIALIZED data" and exits 1.
 */
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

typedef int32_t s32;
typedef uint16_t u16;
#define E1000_SUCCESS 0
#define E1000_ERR_PHY 2
#define PHY_CONTROL_LB (1 << 14)

/* instrumented stand-in for e1000_read_phy_reg_mdic() failure path */
static bool shim_wrote_data;
static s32 read_reg_fails(int reg_offset, u16 *data)
{
	(void)reg_offset;
	/* failure: returns error WITHOUT touching *data — exactly like
	 * e1000_read_phy_reg_mdic() lines 322-335 of e1000_phy.c */
	shim_wrote_data = false;
	return -E1000_ERR_PHY;
}

/* verbatim decision structure of e1000_link_stall_workaround_hv() */
static s32 link_stall_workaround_hv(u16 *stack_probe)
{
	u16 data;		/* line 3840: uninitialized */
	s32 ret_val = E1000_SUCCESS;

	shim_wrote_data = true;	/* will be cleared by the failing read */
	read_reg_fails(0, &data);	/* line 3848: return value dropped */

	*stack_probe = data;	/* observe what the branch below sees */
	if (data & PHY_CONTROL_LB)	/* line 3849: decision on garbage */
		return E1000_SUCCESS;

	/* ... 200ms stall + PHY register writes follow in the real code ... */
	return ret_val;
}

int main(void)
{
	u16 observed = 0xA5A5;	/* sentinel: differs from any legit probe */
	s32 r = link_stall_workaround_hv(&observed);

	printf("read_reg wrote *data: %s\n", shim_wrote_data ? "yes" : "NO (failed)");
	printf("branch observed data: 0x%04x\n", observed);
	if (!shim_wrote_data) {
		printf("decision on UNINITIALIZED data: loopback-check branched on 0x%04x\n",
		       observed);
		printf("DEFECT CONFIRMED (logic replication; hardware path requires e1000 NIC)\n");
		return 1;
	}
	(void)r;
	return 0;
}
