#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
 
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define all(a) a.begin(),a.end()
#define F first
#define S second
#define pb push_back
#define ll long long
#define vi vector<int>
#define pi pair<int,int>
#define mp make_pair

#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 42
#endif

const int mod=1e9+7;
 
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<typename A,typename B> istream& operator>>(istream&,pair<A,B>&);
template<typename A> istream& operator>>(istream&,vector<A>&);
void add(int&,int);
int mul(int,int);
int powz(int,int);
int sub(int,int);
template<typename A> ostream& operator<<(ostream&,vector<A>&);

const int N=100001;

map<pair<int,int>,int>col;
vector<pair<int,int>>adj[N];
int cnt[N];
ll ans[N],sumx[N];
vector<array<int,4>>que[N];
int n,l;
int timer;
vector<int> tin, tout;
vector<vector<int>> up;

void dfs_lca(int v, int p)
{
	assert(v<n);
    tin[v] = ++timer;
    up[v][0] = p;
    for (int i = 1; i <= l; ++i)
        up[v][i] = up[up[v][i-1]][i-1];

    for (auto u : adj[v]) {
        if (u.F != p)
            dfs_lca(u.F, v);
    }

    tout[v] = ++timer;
}

bool is_ancestor(int u, int v)
{
    return tin[u] <= tin[v] && tout[u] >= tout[v];
}

int lca(int u, int v)
{
    if (is_ancestor(u, v))
        return u;
    if (is_ancestor(v, u))
        return v;
    for (int i = l; i >= 0; --i) {
        if (!is_ancestor(up[u][i], v))
            u = up[u][i];
    }
    return up[u][0];
}

void preprocess(int root) {
    tin.resize(n);
    tout.resize(n);
    timer = 0;
    l = ceil(log2(n));
    up.assign(n, vector<int>(l + 1));
    dfs_lca(root, root);
}

void dfs(int u,int p,ll sum){
	for(auto i:que[u]){
		ans[i[0]]+=sum*1ll*i[3];
		ans[i[0]]-=1ll*i[3]*sumx[i[1]];
		ans[i[0]]+=1ll*i[3]*cnt[i[1]]*i[2];
	}
	for(auto i:adj[u]){
		if(i.F!=p){
			sumx[col[{i.F,u}]]+=i.S;
			cnt[col[{i.F,u}]]++;
			dfs(i.F,u,sum+i.S);
			sumx[col[{i.F,u}]]-=i.S;
			cnt[col[{i.F,u}]]--;
		}
		
	}
	
	
}

void solve(){
	int q;
	cin>>n>>q;
	for(int i=0;i<n-1;i++){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		a--;b--;c--;
		col[{a,b}]=col[{b,a}]=c;
		adj[a].pb(mp(b,d));
		adj[b].pb(mp(a,d));
	}
	preprocess(0);
	for(int i=0;i<q;i++){
		int a,b,u,v;
		cin>>u>>v>>a>>b;
		a--;b--;u--;
		int z=lca(a,b);
		que[a].pb({i,u,v,1});
		que[b].pb({i,u,v,1});
		que[z].pb({i,u,v,-2});
	}
	dfs(0,-1,0ll);
	for(int i=0;i<q;i++){
		cout<<ans[i]<<"\n";
	}
		
	
		
}
	
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	int tc=1;
	//~ cin>>tc;
	for(int _=0;_<tc;_++){
		//~ cout<<"Case #"<<_+1<<": ";
		solve();
		if(_!=tc-1)
		cout<<"\n";
	}
}
 
int mul(int a,int b)
{
	return ((a)*1ll*(b))%mod;
}
 
void add(int &a,int b)
{
	a+=b;
	if(a>=mod)a-=mod;
}

int sub(int a,int b){
	a-=b;
	if(a<0){
		a+=mod;
	}
	return a;
}
 
int powz(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)res=mul(res,a);
		b/=2;
		a=mul(a,a);
	}
	return res;
}
 
template <typename A, typename B>
istream& operator>>(istream& input,pair<A,B>& x) {
	input>>x.F>>x.S;
	return input;
}
 
template <typename A>
istream& operator>>(istream& input,vector<A>& x) {
	for(auto& i:x)
		input>>i;
	return input;
}
 
template<typename A>
ostream& operator<<(ostream& output,vector<A>& x) {
	for(auto& i:x)
	    output<<i<<' ';
	return output;	
}


Measured memory_bytes: 51316