/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
const int MAXN= 1e5 +20;
int N=1;
int n;
struct segtree{
	LL tree[MAXN*8],add[MAXN*8];
	void init(int x=0){
		while(N<MAXN)
			N<<=1;
		if(x)
		rep(i,MAXN*8) add[i]=0,tree[i]=x;
		else 
		{
			memset(add,0,sizeof(add));
			memset(tree,0,sizeof(tree));
		}
	}
	LL query(int a,int b,int now=1,int l=1,int r=N+1){
		if(r<=a||l>=b){
			return 0;
		}
		if(r<=b&&l>=a){
			return tree[now]+add[now];
		}
		int mid=(l+r)>>1;
		return (query(a,b,now<<1,l,mid)+query(a,b,(now<<1)+1,mid,r))+add[now];
	}
	LL inc(int a,int b,int val,int now=1,int l=1,int r=N+1){
		if(r<=a||l>=b){
			return tree[now]+add[now];
		}
		if(r<=b&&l>=a){
			add[now]+=val;
			return tree[now]+add[now];
		}
		int mid=(l+r)>>1;
		return (tree[now]=(inc(a,b,val,now<<1,l,mid)+inc(a,b,val,(now<<1)+1,mid,r)))+add[now];
	}	
}segt,cnt,segt2;
struct HLD{
	vector<int> g[MAXN];
	map<mp,int> ID;
	int n=0,heavy[MAXN],size[MAXN],top[MAXN],fa[MAXN][21],depth[MAXN],cnt=0,id[MAXN];
	void add(int u,int v){
		//TWO-WAY
		g[u].PB(v);
		g[v].PB(u);
		ID[II(u,v)]=ID[II(v,u)]=++n;
	}
	void dfs(int now,int prev=0,int deep=1){
		depth[now]=deep;
		fa[now][0]=prev;
		rb(i,1,20){
			fa[now][i]=fa[fa[now][i-1]][i-1];
		}
		size[now]=1;
		heavy[now]=-1;
		for(auto it:g[now]){
			if(it!=prev) {
			dfs(it,now,deep+1),size[now]+=size[it];
			}
		}
		for(auto it:g[now]){
			if(it!=prev){
				if(size[it]*2>=size[now]){
					heavy[now]=it;
				}
			}
		}
	}
	int lca(int u,int v){
	if(depth[u]>depth[v]){
		swap(u,v);
	}
	rl(i,20,0){
		if(fa[v][i]&&depth[fa[v][i]]>=depth[u]){
			v=fa[v][i];
		}
	}
	if(u==v) return u;
	rl(i,20,0){
		if(fa[u][i]!=fa[v][i]){
			u=fa[u][i];
			v=fa[v][i];
		}
	}
	return fa[u][0];
	}
	void dfs2(int now,int prev=-1){
		if(prev==-1) top[now]=now;
		if(heavy[now]>0){
			top[heavy[now]]=top[now];
//			cout<<cnt<<" "<<now<<" "<<heavy[now]<<endl;
			id[ID[II(now,heavy[now])]]=++cnt;
			dfs2(heavy[now],now);
		}
		for(auto it:g[now]){
			if(it!=prev){
				if(it!=heavy[now]){
					top[it]=it;
//					cout<<cnt<<" "<<now<<" "<<it<<endl;
					id[ID[II(now,it)]]=++cnt;
					dfs2(it,now);
				}
			}
		}
	}
	vector<mp> ask(int now,int to,vector<mp> tmp){
		if(now==to) return tmp;
		if(top[now]==now){
			tmp.PB(II(id[ID[II(now,fa[now][0])]],id[ID[II(now,fa[now][0])]]));
			return ask(fa[now][0],to,tmp);
		}
		else{
//				cout<<depth[1]<<" "<<depth[3]<<endl;
			if(depth[top[now]]>=depth[to])
			{
				tmp.PB(II(id[ID[II(now,fa[now][0])]],id[ID[II(top[now],heavy[top[now]])]]));
				return ask(top[now],to,tmp);
			}
			else{
				tmp.PB(II(id[ID[II(now,fa[now][0])]],id[ID[II(to,heavy[to])]]));	
			}
		}
		return tmp;
	}
	vector<mp> query(int u,int v){
		//u->v的段
		int LCA=lca(u,v);
//		cout<<"__"<<LCA<<endl;
		vector<mp> res;
		res=ask(u,LCA,res);
//		cout<<"!"<<endl;
		vector<mp> ano;
		ano=ask(v,LCA,ano);
		for(auto it:ano)
			res.PB(it);
		return res; 
	}
}hld;//ATTENTION : REMEMBER TO MEMSET "FA"
int a[MAXN],b[MAXN],c[MAXN],d[MAXN];
int x[MAXN],y[MAXN],u[MAXN],v[MAXN];
vector<int> col[MAXN],col2[MAXN];
int res[MAXN];
int main(){
	fastio;
	int q;
	get2(n,q);
	segt.init();
	cnt.init();
	segt2.init();
	memset(hld.fa,0,sizeof(hld.fa));
	rb(i,1,n-1){
		get2(a[i],b[i]);
		get2(c[i],d[i]);
		hld.add(a[i],b[i]);
		col[c[i]].PB(i);
	}
	hld.dfs(1);
	hld.dfs2(1);
	rb(i,1,n-1){
		int iid=hld.id[hld.ID[II(a[i],b[i])]];
		segt.inc(iid,iid+1,d[i]);
//		cout<<hld.cnt<<" "<<iid<<" "<<hld.ID[II(a[i],b[i])]<<" "<<d[i]<<endl;
	}
//	cout<<segt.tree[0]<<endl;
	vector<mp> tmp;
	rb(i,1,q){
		cin>>x[i]>>y[i]>>u[i]>>v[i];
		col2[x[i]].PB(i);
	}
	rb(COL,1,n-1){
		for(auto i:col[COL]){
			int iid=hld.id[hld.ID[II(a[i],b[i])]];
			segt2.inc(iid,iid+1,d[i]);
			cnt.inc(iid,iid+1,1);
		}
		for(auto i:col2[COL])
		{
			tmp=hld.query(u[i],v[i]);
			for(auto it:tmp){
				int L,R;
				L=it.FIR,R=it.SEC;
				if(L>R) swap(L,R);
//				cout<<i<<" "<<L<<" "<<R<<" "<<segt.query(L,R+1)<<endl;
				res[i]+=segt.query(L,R+1);
				res[i]-=segt2.query(L,R+1);
				res[i]+=cnt.query(L,R+1)*y[i];
			}
		}
		for(auto i:col[COL]){
			int iid=hld.id[hld.ID[II(a[i],b[i])]];
			segt2.inc(iid,iid+1,-d[i]);
			cnt.inc(iid,iid+1,-1);
		}
		
	}
	rb(i,1,q)
	cout<<res[i]<<endl;
	return 0;
}


Measured memory_bytes: 87464