#include <bits/stdc++.h>
using namespace std;
const int MAX_H = 20;
const int MAX_W = 20;
const int INF = (1 << 30);
int H, W;
int memo[MAX_H][MAX_W][MAX_H][MAX_W];
vector<string> input() {
  vector<string> ret;
  cin >> H >> W;
  for (int i = 0; i < H; i++) {
    string str;
    cin >> str;
    ret.push_back(str);
  }
  return ret;
}
bool check(pair<int, int> pos, vector<string> field) {
  if (!(0 <= pos.first && pos.first < H && 0 <= pos.second && pos.second < W))
    return false;
  if (field[pos.first][pos.second] == '#') return false;
  return true;
}
int bfs(pair<int, int> start, pair<int, int> goal, vector<string> field) {
  const static int dy[4] = {0, 1, 0, -1};
  const static int dx[4] = {1, 0, -1, 0};
  bool visited[MAX_H][MAX_W];
  for (int i = 0; i < MAX_H; i++) {
    for (int j = 0; j < MAX_W; j++) {
      visited[i][j] = false;
    }
  }
  if (memo[start.first][start.second][goal.first][goal.second] != INF) {
    return memo[start.first][start.second][goal.first][goal.second];
  }
  queue<pair<int, pair<int, int> > > que = queue<pair<int, pair<int, int> > >();
  que.push(pair<int, pair<int, int> >(0, start));
  while (que.size()) {
    pair<int, pair<int, int> > state = que.front();
    que.pop();
    if (visited[state.second.first][state.second.second]) {
      continue;
    }
    visited[state.second.first][state.second.second] = true;
    memo[start.first][start.second][state.second.first][state.second.second] =
        state.first;
    memo[state.second.first][state.second.second][start.first][start.second] =
        state.first;
    for (int i = 0; i < 4; i++) {
      pair<int, pair<int, int> > next_state = pair<int, pair<int, int> >(
          state.first + 1, pair<int, int>(state.second.first + dy[i],
                                          state.second.second + dx[i]));
      if (check(next_state.second, field)) {
        if (next_state.second == goal) return next_state.first;
        que.push(next_state);
      }
    }
  }
  return -1;
}
int solve(vector<string> field) {
  int res = -1;
  for (int sy = 0; sy < H; sy++) {
    for (int sx = 0; sx < W; sx++) {
      if (field[sy][sx] == '#') continue;
      for (int gy = 0; gy < H; gy++) {
        for (int gx = 0; gx < W; gx++) {
          if (field[gy][gx] == '#') continue;
          res = max(res,
                    bfs(pair<int, int>(sy, sx), pair<int, int>(gy, gx), field));
        }
      }
    }
  }
  return res;
}
void init() {
  for (int i = 0; i < MAX_H; i++) {
    for (int j = 0; j < MAX_W; j++) {
      for (int k = 0; k < MAX_H; k++) {
        for (int l = 0; l < MAX_W; l++) {
          memo[i][j][k][l] = INF;
        }
      }
    }
  }
}
int main() {
  init();
  cout << solve(input()) << endl;
  return 0;
}
