def bfs(maze,sx, sy,gx, gy):
    """maze内の S から G への最短距離を求める。たどり着けないと-1"""
    # for y, row in enumerate(maze):
    #     for x, col in enumerate(row):
    #         if col == 'S':
    #             sy, sx = y, x
    #         if col == 'G':
    #             gy, gx = y, x

    # 各地点までの最短距離の配列（壁以外を-1にする)
    d = [[-1 if col != '#' else col for col in row] for row in maze]

    # スタート地点をキューに入れ、その点の距離を0にする
    que = [(sy, sx)]
    d[sy][sx] = 0

    # キューが空(たどり着かない)かゴールにたどり着くまでキューの先頭を処理
    while que and que[0] != (gy, gx):
        py, px = que.pop(0)
        # 4方向を処理
        for ny, nx in (py - 1, px), (py + 1, px), (py, px - 1), (py, px + 1):
            if 0 <= ny < len(d) and 0 <= nx < len(d[ny]) and d[ny][nx] == -1:
                # -1の場所には移動できるのでキューに追加、nはpの距離+1で確定
                que.append((ny, nx))
                d[ny][nx] = d[py][px] + 1

    return d[gy][gx]


def solve():
    maze = []
    h, w = map(int, input().split())
    for _ in range(h):
        maze.append(input())
        
    # maze = [
    #     # '#S######.#',
    #     # '.......#.#',
    #     # '.#.##.##.#',
    #     # '.#........',
    #     # '##.##.####',
    #     # '....#....#',
    #     # '.#######.#',
    #     # '....#.....',
    #     # '.####.###.',
    #     # '....#...G#',
        
    #     '...#.',
    #     '.#.#.',
    #     '.#...',
    # ]
    
    max = 0
    for sx in range(w):
        for sy in range(h):
            for gx in range(w):
                for gy in range(h):
                    ans = bfs(maze,sx, sy, gx, gy )
                    if ans != '#':
                        if int(ans) > max:
                            max = int(ans)
                        
    print(max)

if __name__ == '__main__':
    solve()