#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define int ll
#define rep(i,n) for(int i=0;i<n;i++)
#define all(in) in.begin(), in.end()
#define INF (sizeof(int) == 4 ? (int)1e9:(int)1e18)
#define EPS 0.0000000001
template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }
template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }
template<typename Head, typename Value> auto vectors(const Head &head, const Value &v) { return vector<Value>(head, v); }
template<typename Head, typename... Tail> auto vectors(Head x, Tail... tail) { auto inner = vectors(tail...); return vector<decltype(inner)>(x, inner); }
using ld  = long double;
using pii = pair<int,int>;
using piii = pair<int,pii>;
int W,H;
vector<string>grid;
vector<vector<int>>memo;
bool valid(int x,int y){return (0<=x&&x<W)&&(0<=y&&y<H);}
int dx[]={0,0,1,-1}, dy[]={1,-1,0,0};
void dfs(pii crt, pii e){
    rep(i,4)rep(j,4){
        int tx = crt.second + dx[i];
        int ty = crt.first + dy[i];
        if(valid(tx,ty) and grid[ty][tx] != '#'){
            if(memo[ty][tx] > memo[crt.first][crt.second]) {
                memo[ty][tx] = memo[crt.first][crt.second] + 1;
                if(ty == e.first and tx == e.second){
                    
                } else {
                    dfs(pii(ty,tx),e);
                }
            }
            
        }
    }
}
int solve(pii s, pii e){
    memo = vector<vector<int>>(H,vector<int>(W,500));
    memo[s.first][s.second] = 0;
    dfs(s,e);
    return memo[e.first][e.second];
    
}
signed main(){
    cin >> H >> W;
    grid = vector<string>(H);
    for(auto&s : grid) cin >> s;
    int ans = -1;
    rep(i,H)rep(j,W){
        rep(k,H)rep(l,W){
            if(i == k and j == l) continue;
            if(grid[i][j] == '#' or grid[k][l] == '#')continue;
            cmax(ans, solve(pii(i,j),pii(k,l)));
        }
    }
    cout << ans << endl;
}
